1
1
#! /bin/bash
2
+ set -euo pipefail
2
3
3
- # Free disk space on Linux GitHub action runners
4
+ # Free disk space on Linux GitHub action runners.
4
5
# Script inspired by https://github.com/jlumbroso/free-disk-space
5
6
6
- # print a line of the specified character
7
+ # When updating to a new ubuntu version (e.g. from ubuntu-24.04):
8
+ # - Check that there are no docker images preinstalled with `docker image ls`
9
+ # - Check that there are no big packages preinstalled that we aren't using
10
+ # - Check that all directores we are removing are still present (look at the warnings)
11
+
12
+ # Print a line of the specified character.
7
13
printSeparationLine () {
8
14
for (( i = 0 ; i < 80 ; i++ )) ; do
9
15
printf " %s" " $1 "
10
16
done
11
17
printf " \n"
12
18
}
13
19
14
- # compute available space
20
+ # Compute available space.
15
21
# REF: https://unix.stackexchange.com/a/42049/60849
16
22
# REF: https://stackoverflow.com/a/450821/408734
17
- getAvailableSpace () { echo $( df -a | awk ' NR > 1 {avail+=$4} END {print avail}' ) ; }
23
+ getAvailableSpace () {
24
+ df -a | awk ' NR > 1 {avail+=$4} END {print avail}'
25
+ }
18
26
19
- # make Kb human readable (assume the input is Kb)
27
+ # Make Kb human readable (assume the input is Kb).
20
28
# REF: https://unix.stackexchange.com/a/44087/60849
21
- formatByteCount () { echo $( numfmt --to=iec-i --suffix=B --padding=7 $1 ' 000' ) ; }
29
+ formatByteCount () {
30
+ numfmt --to=iec-i --suffix=B --padding=7 " $1 " ' 000'
31
+ }
32
+
33
+ # Check if the architecture is x86.
34
+ isX86 () {
35
+ local arch
36
+ arch=$( uname -m)
37
+ if [ " $arch " = " x86_64" ]; then
38
+ return 0
39
+ else
40
+ return 1
41
+ fi
42
+ }
43
+
44
+ # Execute a task, printing how much space was saved and how long it took to run the task
45
+ execAndMeasure () {
46
+ local task_name=${1}
47
+
48
+ local start
49
+ start=$( date +%s)
50
+
51
+ local before
52
+ before=$( getAvailableSpace)
53
+
54
+ # Run the task. Skip the first argument because it's the task name.
55
+ " ${@: 2} "
22
56
23
- # macro to output saved space
24
- printSavedSpace () {
25
- # Disk space before the operation
26
- local before=${1}
27
- local title=${2:- }
57
+ local end
58
+ end=$( date +%s)
28
59
29
60
local after
30
61
after=$( getAvailableSpace)
62
+
63
+ # How much space was saved.
31
64
local saved=$(( after - before))
65
+ # How long the task took.
66
+ local seconds_taken=$(( end - start))
32
67
33
- echo " "
34
- printSeparationLine " *"
35
- if [ -n " ${title} " ]; then
36
- echo " => ${title} : Saved $( formatByteCount " $saved " ) "
37
- else
38
- echo " => Saved $( formatByteCount " $saved " ) "
39
- fi
40
- printSeparationLine " *"
41
- echo " "
68
+ echo " ==> ${task_name} : Saved $( formatByteCount " $saved " ) in $seconds_taken seconds"
42
69
}
43
70
44
- # macro to print output of df with caption
71
+ # Print output of df with caption. It shows information about disk space.
45
72
printDF () {
46
73
local caption=${1}
47
74
@@ -52,91 +79,164 @@ printDF() {
52
79
echo " "
53
80
df -h
54
81
printSeparationLine " ="
82
+ echo " "
55
83
}
56
84
57
- removeDir () {
58
- dir=${1}
59
-
60
- local before
61
- before=$( getAvailableSpace)
62
-
63
- sudo rm -rf " $dir " || true
85
+ removeUnusedDirsAndFiles () {
86
+ local to_remove=(
87
+ " /etc/mysql"
88
+ " /usr/local/aws-sam-cli"
89
+ " /usr/local/doc/cmake"
90
+ " /usr/local/julia" *
91
+ " /usr/local/lib/android"
92
+ " /usr/local/share/chromedriver-" *
93
+ " /usr/local/share/chromium"
94
+ " /usr/local/share/cmake-" *
95
+ " /usr/local/share/edge_driver"
96
+ " /usr/local/share/gecko_driver"
97
+ " /usr/local/share/icons"
98
+ " /usr/local/share/vim"
99
+ " /usr/local/share/emacs"
100
+ " /usr/local/share/powershell"
101
+ " /usr/local/share/vcpkg"
102
+ " /usr/share/apache-maven-" *
103
+ " /usr/share/gradle-" *
104
+ " /usr/share/java"
105
+ " /usr/share/kotlinc"
106
+ " /usr/share/miniconda"
107
+ " /usr/share/php"
108
+ " /usr/share/ri"
109
+ " /usr/share/swift"
110
+
111
+ # binaries
112
+ " /usr/local/bin/azcopy"
113
+ " /usr/local/bin/bicep"
114
+ " /usr/local/bin/ccmake"
115
+ " /usr/local/bin/cmake-" *
116
+ " /usr/local/bin/cmake"
117
+ " /usr/local/bin/cpack"
118
+ " /usr/local/bin/ctest"
119
+ " /usr/local/bin/helm"
120
+ " /usr/local/bin/kind"
121
+ " /usr/local/bin/kustomize"
122
+ " /usr/local/bin/minikube"
123
+ " /usr/local/bin/packer"
124
+ " /usr/local/bin/phpunit"
125
+ " /usr/local/bin/pulumi-" *
126
+ " /usr/local/bin/pulumi"
127
+ " /usr/local/bin/stack"
128
+
129
+ # Haskell runtime
130
+ " /usr/local/.ghcup"
131
+
132
+ # Azure
133
+ " /opt/az"
134
+ " /usr/share/az_" *
135
+
136
+ # Environemnt variable set by GitHub Actions
137
+ " $AGENT_TOOLSDIRECTORY "
138
+ )
139
+
140
+ local existing=()
141
+ for element in " ${to_remove[@]} " ; do
142
+ if [ ! -e " $element " ]; then
143
+ echo " ::warning::Directory or file $element does not exist, skipping."
144
+ else
145
+ existing+=(" $element " )
146
+ fi
147
+ done
64
148
65
- printSavedSpace " $before " " $dir "
149
+ execAndMeasure " Removed unused directories " sudo rm -rf " ${existing[@]} "
66
150
}
67
151
68
- execAndMeasureSpaceChange () {
69
- local operation=${1} # Function to execute
70
- local title=${2}
71
-
72
- local before
73
- before=$( getAvailableSpace)
74
- $operation
75
-
76
- printSavedSpace " $before " " $title "
152
+ removeNodeModules () {
153
+ sudo npm uninstall -g \
154
+ " @bazel/bazelisk" \
155
+ " grunt" \
156
+ " gulp" \
157
+ " lerna" \
158
+ " n" \
159
+ " newman" \
160
+ " parcel" \
161
+ " typescript" \
162
+ " webpack-cli" \
163
+ " webpack" \
164
+ " yarn"
77
165
}
78
166
79
- # Remove large packages
80
- # REF: https://github.com/apache/flink/blob/master/tools/azure-pipelines/free_disk_space.sh
167
+ # Remove unused packages.
81
168
cleanPackages () {
82
- sudo apt-get -qq remove -y --fix-missing \
83
- ' ^aspnetcore-.*' \
84
- ' ^dotnet-.*' \
85
- ' ^llvm-.*' \
86
- ' php.*' \
87
- ' ^mongodb-.*' \
88
- ' ^mysql-.*' \
89
- ' azure-cli' \
90
- ' google-chrome-stable' \
91
- ' firefox' \
92
- ' powershell' \
93
- ' mono-devel' \
94
- ' libgl1-mesa-dri' \
95
- ' google-cloud-sdk' \
96
- ' google-cloud-cli'
169
+ local packages=(
170
+ ' .*-icon-theme$'
171
+ ' ^aspnetcore-.*'
172
+ ' ^dotnet-.*'
173
+ ' ^java-*'
174
+ ' ^libllvm.*'
175
+ ' ^llvm-.*'
176
+ ' ^mercurial.*'
177
+ ' ^mysql-.*'
178
+ ' ^vim.*'
179
+ ' ^fonts-.*'
180
+ ' azure-cli'
181
+ ' buildah'
182
+ ' cpp-13'
183
+ ' firefox'
184
+ ' gcc-12'
185
+ ' gcc-13'
186
+ ' gcc-14'
187
+ ' gcc'
188
+ ' g++-14'
189
+ ' gfortran-14'
190
+ ' groff-base'
191
+ ' kubectl'
192
+ ' libgl1-mesa-dri'
193
+ ' microsoft-edge-stable'
194
+ ' php.*'
195
+ ' podman'
196
+ ' powershell'
197
+ ' skopeo'
198
+ ' snapd'
199
+ ' tmux'
200
+ )
201
+
202
+ if isX86; then
203
+ packages+=(
204
+ ' google-chrome-stable'
205
+ ' google-cloud-cli'
206
+ )
207
+ fi
208
+
209
+ sudo apt-get purge -y --autoremove --fix-missing " ${packages[@]} "
97
210
211
+ echo " => apt-get autoremove"
98
212
sudo apt-get autoremove -y || echo " ::warning::The command [sudo apt-get autoremove -y] failed"
99
213
sudo apt-get clean || echo " ::warning::The command [sudo apt-get clean] failed failed"
100
214
}
101
215
102
- # Remove Docker images
103
- cleanDocker () {
104
- echo " Removing the following docker images:"
105
- sudo docker image ls
106
- echo " Removing docker images..."
107
- sudo docker image prune --all --force || true
108
- }
109
-
110
- # Remove Swap storage
111
- cleanSwap () {
112
- sudo swapoff -a || true
113
- sudo rm -rf /mnt/swapfile || true
114
- free -h
115
- }
116
-
117
- # Display initial disk space stats
118
-
119
- AVAILABLE_INITIAL=$( getAvailableSpace)
216
+ removePythonPackages () {
217
+ local packages=(
218
+ )
120
219
121
- printDF " BEFORE CLEAN-UP: "
122
- echo " "
123
-
124
- removeDir /usr/local/lib/android
125
- removeDir /usr/share/dotnet
220
+ if isX86 ; then
221
+ packages+=(
222
+ ' ansible-core '
223
+ )
224
+ fi
126
225
127
- # Haskell runtime
128
- removeDir /opt/ghc
129
- removeDir /usr/local/.ghcup
226
+ for p in " ${packages[@]} " ; do
227
+ sudo pipx uninstall " $p "
228
+ done
229
+ }
130
230
131
- execAndMeasureSpaceChange cleanPackages " Large misc. packages"
132
- execAndMeasureSpaceChange cleanDocker " Docker images"
133
- execAndMeasureSpaceChange cleanSwap " Swap storage"
231
+ main () {
232
+ printDF " BEFORE CLEAN-UP:"
134
233
135
- # Output saved space statistic
136
- echo " "
137
- printDF " AFTER CLEAN-UP:"
234
+ execAndMeasure " Unused packages" cleanPackages
235
+ execAndMeasure " Node modules" removeNodeModules
236
+ execAndMeasure " Python Packages" removePythonPackages
237
+ removeUnusedDirsAndFiles
138
238
139
- echo " "
140
- echo " "
239
+ printDF " AFTER CLEAN-UP: "
240
+ }
141
241
142
- printSavedSpace " $AVAILABLE_INITIAL " " Total saved "
242
+ execAndMeasure " Total" main
0 commit comments