1 | #!/bin/bash
|
---|
2 | # $Id: VirtualBox_Uninstall.tool 106061 2024-09-16 14:03:52Z vboxsync $
|
---|
3 | ## @file
|
---|
4 | # VirtualBox Uninstaller Script.
|
---|
5 | #
|
---|
6 |
|
---|
7 | #
|
---|
8 | # Copyright (C) 2007-2024 Oracle and/or its affiliates.
|
---|
9 | #
|
---|
10 | # This file is part of VirtualBox base platform packages, as
|
---|
11 | # available from https://www.virtualbox.org.
|
---|
12 | #
|
---|
13 | # This program is free software; you can redistribute it and/or
|
---|
14 | # modify it under the terms of the GNU General Public License
|
---|
15 | # as published by the Free Software Foundation, in version 3 of the
|
---|
16 | # License.
|
---|
17 | #
|
---|
18 | # This program is distributed in the hope that it will be useful, but
|
---|
19 | # WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
21 | # General Public License for more details.
|
---|
22 | #
|
---|
23 | # You should have received a copy of the GNU General Public License
|
---|
24 | # along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
25 | #
|
---|
26 | # SPDX-License-Identifier: GPL-3.0-only
|
---|
27 | #
|
---|
28 |
|
---|
29 | # Override any funny stuff from the user.
|
---|
30 | export PATH="/bin:/usr/bin:/sbin:/usr/sbin:$PATH"
|
---|
31 |
|
---|
32 | #
|
---|
33 | # Display a simple welcome message first.
|
---|
34 | #
|
---|
35 | echo ""
|
---|
36 | echo "Welcome to the VirtualBox uninstaller script."
|
---|
37 | echo ""
|
---|
38 |
|
---|
39 | #
|
---|
40 | # Check for arguments and display
|
---|
41 | #
|
---|
42 | my_default_prompt=0
|
---|
43 | if test "$#" != "0"; then
|
---|
44 | if test "$#" != "1" -o "$1" != "--unattended"; then
|
---|
45 | echo "Error: Unknown argument(s): $*"
|
---|
46 | echo ""
|
---|
47 | echo "Usage: uninstall.sh [--unattended]"
|
---|
48 | echo ""
|
---|
49 | echo "If the '--unattended' option is not given, you will be prompted"
|
---|
50 | echo "for a Yes/No before doing the actual uninstallation."
|
---|
51 | echo ""
|
---|
52 | exit 4;
|
---|
53 | fi
|
---|
54 | my_default_prompt="Yes"
|
---|
55 | fi
|
---|
56 |
|
---|
57 | #
|
---|
58 | # Collect directories and files to remove.
|
---|
59 | # Note: Do NOT attempt adding directories or filenames with spaces!
|
---|
60 | #
|
---|
61 | declare -a my_directories
|
---|
62 | declare -a my_files
|
---|
63 |
|
---|
64 | # Users files first
|
---|
65 | test -f "${HOME}/Library/LaunchAgents/org.virtualbox.vboxwebsrv.plist" && my_files+=("${HOME}/Library/LaunchAgents/org.virtualbox.vboxwebsrv.plist")
|
---|
66 |
|
---|
67 | test -d /Library/StartupItems/VirtualBox/ && my_directories+=("/Library/StartupItems/VirtualBox/")
|
---|
68 | test -d /Library/Receipts/VBoxStartupItems.pkg/ && my_directories+=("/Library/Receipts/VBoxStartupItems.pkg/")
|
---|
69 |
|
---|
70 | test -d "/Library/Application Support/VirtualBox/LaunchDaemons/" && my_directories+=("/Library/Application Support/VirtualBox/LaunchDaemons/")
|
---|
71 | test -d "/Library/Application Support/VirtualBox/VBoxDrv.kext/" && my_directories+=("/Library/Application Support/VirtualBox/VBoxDrv.kext/")
|
---|
72 | test -d "/Library/Application Support/VirtualBox/VBoxUSB.kext/" && my_directories+=("/Library/Application Support/VirtualBox/VBoxUSB.kext/")
|
---|
73 | test -d "/Library/Application Support/VirtualBox/VBoxNetFlt.kext/" && my_directories+=("/Library/Application Support/VirtualBox/VBoxNetFlt.kext/")
|
---|
74 | test -d "/Library/Application Support/VirtualBox/VBoxNetAdp.kext/" && my_directories+=("/Library/Application Support/VirtualBox/VBoxNetAdp.kext/")
|
---|
75 | # Pre 4.3.0rc1 locations:
|
---|
76 | test -d /Library/Extensions/VBoxDrv.kext/ && my_directories+=("/Library/Extensions/VBoxDrv.kext/")
|
---|
77 | test -d /Library/Extensions/VBoxUSB.kext/ && my_directories+=("/Library/Extensions/VBoxUSB.kext/")
|
---|
78 | test -d /Library/Extensions/VBoxNetFlt.kext/ && my_directories+=("/Library/Extensions/VBoxNetFlt.kext/")
|
---|
79 | test -d /Library/Extensions/VBoxNetAdp.kext/ && my_directories+=("/Library/Extensions/VBoxNetAdp.kext/")
|
---|
80 | # Tiger support is obsolete, but we leave it here for a clean removing of older
|
---|
81 | # VirtualBox versions
|
---|
82 | test -d /Library/Extensions/VBoxDrvTiger.kext/ && my_directories+=("/Library/Extensions/VBoxDrvTiger.kext/")
|
---|
83 | test -d /Library/Extensions/VBoxUSBTiger.kext/ && my_directories+=("/Library/Extensions/VBoxUSBTiger.kext/")
|
---|
84 | test -d /Library/Receipts/VBoxKEXTs.pkg/ && my_directories+=("/Library/Receipts/VBoxKEXTs.pkg/")
|
---|
85 |
|
---|
86 | test -f /usr/bin/VirtualBox && my_files+=("/usr/bin/VirtualBox")
|
---|
87 | test -f /usr/bin/VirtualBoxVM && my_files+=("/usr/bin/VirtualBoxVM")
|
---|
88 | test -f /usr/bin/VBoxManage && my_files+=("/usr/bin/VBoxManage")
|
---|
89 | test -f /usr/bin/VBoxVRDP && my_files+=("/usr/bin/VBoxVRDP")
|
---|
90 | test -f /usr/bin/VBoxHeadless && my_files+=("/usr/bin/VBoxHeadless")
|
---|
91 | test -f /usr/bin/vboxwebsrv && my_files+=("/usr/bin/vboxwebsrv")
|
---|
92 | test -f /usr/bin/VBoxBugReport && my_files+=("/usr/bin/VBoxBugReport")
|
---|
93 | test -f /usr/bin/VBoxBalloonCtrl && my_files+=("/usr/bin/VBoxBalloonCtrl")
|
---|
94 | test -f /usr/bin/VBoxAutostart && my_files+=("/usr/bin/VBoxAutostart")
|
---|
95 | test -f /usr/bin/VBoxDTrace && my_files+=("/usr/bin/VBoxDTrace")
|
---|
96 | test -f /usr/bin/VBoxAudioTest && my_files+=("/usr/bin/VBoxAudioTest")
|
---|
97 | test -f /usr/bin/vbox-img && my_files+=("/usr/bin/vbox-img")
|
---|
98 | test -f /usr/local/bin/VirtualBox && my_files+=("/usr/local/bin/VirtualBox")
|
---|
99 | test -f /usr/local/bin/VirtualBoxVM && my_files+=("/usr/local/bin/VirtualBoxVM")
|
---|
100 | test -f /usr/local/bin/VBoxManage && my_files+=("/usr/local/bin/VBoxManage")
|
---|
101 | test -f /usr/local/bin/VBoxVRDP && my_files+=("/usr/local/bin/VBoxVRDP")
|
---|
102 | test -f /usr/local/bin/VBoxHeadless && my_files+=("/usr/local/bin/VBoxHeadless")
|
---|
103 | test -f /usr/local/bin/vboxwebsrv && my_files+=("/usr/local/bin/vboxwebsrv")
|
---|
104 | test -f /usr/local/bin/VBoxBugReport && my_files+=("/usr/local/bin/VBoxBugReport")
|
---|
105 | test -f /usr/local/bin/VBoxBalloonCtrl && my_files+=("/usr/local/bin/VBoxBalloonCtrl")
|
---|
106 | test -f /usr/local/bin/VBoxAutostart && my_files+=("/usr/local/bin/VBoxAutostart")
|
---|
107 | test -f /usr/local/bin/VBoxDTrace && my_files+=("/usr/local/bin/VBoxDTrace")
|
---|
108 | test -f /usr/local/bin/VBoxAudioTest && my_files+=("/usr/local/bin/VBoxAudioTest")
|
---|
109 | test -f /usr/local/bin/vbox-img && my_files+=("/usr/local/bin/vbox-img")
|
---|
110 | test -d /Library/Receipts/VirtualBoxCLI.pkg/ && my_directories+=("/Library/Receipts/VirtualBoxCLI.pkg/")
|
---|
111 | test -f /Library/LaunchDaemons/org.virtualbox.startup.plist && my_files+=("/Library/LaunchDaemons/org.virtualbox.startup.plist")
|
---|
112 |
|
---|
113 | test -d /Applications/VirtualBox.app/ && my_directories+=("/Applications/VirtualBox.app/")
|
---|
114 | test -d /Library/Receipts/VirtualBox.pkg/ && my_directories+=("/Library/Receipts/VirtualBox.pkg/")
|
---|
115 |
|
---|
116 | # legacy
|
---|
117 | test -d /Library/Receipts/VBoxDrv.pkg/ && my_directories+=("/Library/Receipts/VBoxDrv.pkg/")
|
---|
118 | test -d /Library/Receipts/VBoxUSB.pkg/ && my_directories+=("/Library/Receipts/VBoxUSB.pkg/")
|
---|
119 |
|
---|
120 | # python stuff
|
---|
121 | python_versions="\
|
---|
122 | 2.6 \
|
---|
123 | 2.7 \
|
---|
124 | 3.3 \
|
---|
125 | 3.4 \
|
---|
126 | 3.5 \
|
---|
127 | 3.6 \
|
---|
128 | 3.7 \
|
---|
129 | 3.8 \
|
---|
130 | 3.9 \
|
---|
131 | 3.10 \
|
---|
132 | 3.11 \
|
---|
133 | 3.12"
|
---|
134 | for p in $python_versions; do
|
---|
135 | test -f /Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.py && my_files+=("/Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.py")
|
---|
136 | test -f /Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.pyc && my_files+=("/Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.pyc")
|
---|
137 | test -f /Library/Python/$p/site-packages/vboxapi/__init__.py && my_files+=("/Library/Python/$p/site-packages/vboxapi/__init__.py")
|
---|
138 | test -f /Library/Python/$p/site-packages/vboxapi/__init__.pyc && my_files+=("/Library/Python/$p/site-packages/vboxapi/__init__.pyc")
|
---|
139 | test -f /Library/Python/$p/site-packages/vboxapi-1.0-py$p.egg-info && my_files+=("/Library/Python/$p/site-packages/vboxapi-1.0-py$p.egg-info")
|
---|
140 | test -d /Library/Python/$p/site-packages/vboxapi/ && my_directories+=("/Library/Python/$p/site-packages/vboxapi/")
|
---|
141 | done
|
---|
142 |
|
---|
143 | #
|
---|
144 | # Collect KEXTs to remove.
|
---|
145 | # Note that the unload order is significant.
|
---|
146 | #
|
---|
147 | declare -a my_kexts
|
---|
148 | for kext in org.virtualbox.kext.VBoxUSB org.virtualbox.kext.VBoxNetFlt org.virtualbox.kext.VBoxNetAdp org.virtualbox.kext.VBoxDrv; do
|
---|
149 | if /usr/sbin/kextstat -b $kext -l | grep -q $kext; then
|
---|
150 | my_kexts+=("$kext")
|
---|
151 | fi
|
---|
152 | done
|
---|
153 |
|
---|
154 | #
|
---|
155 | # Collect packages to forget
|
---|
156 | #
|
---|
157 | my_pb='org\.virtualbox\.pkg\.'
|
---|
158 | my_pkgs=`/usr/sbin/pkgutil --pkgs="${my_pb}vboxkexts|${my_pb}vboxstartupitems|${my_pb}virtualbox|${my_pb}virtualboxcli"`
|
---|
159 |
|
---|
160 | #
|
---|
161 | # Did we find anything to uninstall?
|
---|
162 | #
|
---|
163 | if test -z "${my_directories[*]}" -a -z "${my_files[*]}" -a -z "${my_kexts[*]}" -a -z "$my_pkgs"; then
|
---|
164 | echo "No VirtualBox files, directories, KEXTs or packages to uninstall."
|
---|
165 | echo "Done."
|
---|
166 | exit 0;
|
---|
167 | fi
|
---|
168 |
|
---|
169 | #
|
---|
170 | # Look for running VirtualBox processes and warn the user
|
---|
171 | # if something is running. Since deleting the files of
|
---|
172 | # running processes isn't fatal as such, we will leave it
|
---|
173 | # to the user to choose whether to continue or not.
|
---|
174 | #
|
---|
175 | # Note! comm isn't supported on Tiger, so we make -c to do the stripping.
|
---|
176 | #
|
---|
177 | my_processes="`ps -axco 'pid uid command' | grep -wEe '(VirtualBox|VirtualBoxVM|VBoxManage|VBoxHeadless|vboxwebsrv|VBoxXPCOMIPCD|VBoxSVC|VBoxNetDHCP|VBoxNetNAT)' | grep -vw grep | grep -vw VirtualBox_Uninstall.tool | tr '\n' '\a'`";
|
---|
178 | if test -n "$my_processes"; then
|
---|
179 | echo 'Warning! Found the following active VirtualBox processes:'
|
---|
180 | echo "$my_processes" | tr '\a' '\n'
|
---|
181 | echo ""
|
---|
182 | echo "We recommend that you quit all VirtualBox processes before"
|
---|
183 | echo "uninstalling the product."
|
---|
184 | echo ""
|
---|
185 | if test "$my_default_prompt" != "Yes"; then
|
---|
186 | echo "Do you wish to continue none the less (Yes/No)?"
|
---|
187 | read my_answer
|
---|
188 | if test "$my_answer" != "Yes" -a "$my_answer" != "YES" -a "$my_answer" != "yes"; then
|
---|
189 | echo "Aborting uninstall. (answer: '$my_answer')".
|
---|
190 | exit 2;
|
---|
191 | fi
|
---|
192 | echo ""
|
---|
193 | my_answer=""
|
---|
194 | fi
|
---|
195 | fi
|
---|
196 |
|
---|
197 | #
|
---|
198 | # Display the files and directories that will be removed
|
---|
199 | # and get the user's consent before continuing.
|
---|
200 | #
|
---|
201 | if test -n "${my_files[*]}" -o -n "${my_directories[*]}"; then
|
---|
202 | echo "The following files and directories (bundles) will be removed:"
|
---|
203 | for file in "${my_files[@]}"; do echo " $file"; done
|
---|
204 | for dir in "${my_directories[@]}"; do echo " $dir"; done
|
---|
205 | echo ""
|
---|
206 | fi
|
---|
207 | if test -n "${my_kexts[*]}"; then
|
---|
208 | echo "And the following KEXTs will be unloaded:"
|
---|
209 | for kext in "${my_kexts[@]}"; do echo " $kext"; done
|
---|
210 | echo ""
|
---|
211 | fi
|
---|
212 | if test -n "$my_pkgs"; then
|
---|
213 | echo "And the traces of following packages will be removed:"
|
---|
214 | for kext in $my_pkgs; do echo " $kext"; done
|
---|
215 | echo ""
|
---|
216 | fi
|
---|
217 |
|
---|
218 | if test "$my_default_prompt" != "Yes"; then
|
---|
219 | echo "Do you wish to uninstall VirtualBox (Yes/No)?"
|
---|
220 | read my_answer
|
---|
221 | if test "$my_answer" != "Yes" -a "$my_answer" != "YES" -a "$my_answer" != "yes"; then
|
---|
222 | echo "Aborting uninstall. (answer: '$my_answer')".
|
---|
223 | exit 2;
|
---|
224 | fi
|
---|
225 | echo ""
|
---|
226 | fi
|
---|
227 |
|
---|
228 | my_fuse_macos_core_uninstall=0
|
---|
229 | if test "$my_default_prompt" != "Yes" -a -f "/Library/Filesystems/osxfuse.fs/Contents/Resources/uninstall_osxfuse.app/Contents/Resources/Scripts/uninstall_osxfuse.sh"; then
|
---|
230 | echo "VirtualBox detected the FUSE for macOS core package which might've been installed"
|
---|
231 | echo "by VirtualBox itself for the vboximg-mount utility. Do you wish to uninstall"
|
---|
232 | echo "the FUSE for macOS core package (Yes/No)?"
|
---|
233 | read my_answer
|
---|
234 | if test "$my_answer" == "Yes" -o "$my_answer" == "YES" -o "$my_answer" == "yes"; then
|
---|
235 | my_fuse_macos_core_uninstall=1;
|
---|
236 | fi
|
---|
237 | echo ""
|
---|
238 | fi
|
---|
239 |
|
---|
240 | #
|
---|
241 | # Unregister has to be done before the files are removed.
|
---|
242 | #
|
---|
243 | LSREGISTER=/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister
|
---|
244 | if [ -e ${LSREGISTER} ]; then
|
---|
245 | ${LSREGISTER} -u /Applications/VirtualBox.app > /dev/null
|
---|
246 | ${LSREGISTER} -u /Applications/VirtualBox.app/Contents/Resources/vmstarter.app > /dev/null
|
---|
247 | fi
|
---|
248 |
|
---|
249 | #
|
---|
250 | # Display the sudo usage instructions and execute the command.
|
---|
251 | #
|
---|
252 | echo "The uninstallation processes requires administrative privileges"
|
---|
253 | echo "because some of the installed files cannot be removed by a normal"
|
---|
254 | echo "user. You may be prompted for your password now..."
|
---|
255 | echo ""
|
---|
256 |
|
---|
257 | if test -n "${my_files[*]}" -o -n "${my_directories[*]}"; then
|
---|
258 | /usr/bin/sudo -p "Please enter %u's password:" /bin/rm -Rf "${my_files[@]}" "${my_directories[@]}"
|
---|
259 | my_rc=$?
|
---|
260 | if test "$my_rc" -ne 0; then
|
---|
261 | echo "An error occurred durning 'sudo rm', there should be a message above. (rc=$my_rc)"
|
---|
262 | test -x /usr/bin/sudo || echo "warning: Cannot find /usr/bin/sudo or it's not an executable."
|
---|
263 | test -x /bin/rm || echo "warning: Cannot find /bin/rm or it's not an executable"
|
---|
264 | echo ""
|
---|
265 | echo "The uninstall failed. Please retry."
|
---|
266 | test "$my_default_prompt" != "Yes" && read -p "Press <ENTER> to exit"
|
---|
267 | exit 1;
|
---|
268 | fi
|
---|
269 | fi
|
---|
270 |
|
---|
271 | if test "$my_fuse_macos_core_uninstall" != 0; then
|
---|
272 | echo "Uninstalling the FUSE for macOS core package"
|
---|
273 | /usr/bin/sudo -p "Please enter %u's password:" /Library/Filesystems/osxfuse.fs/Contents/Resources/uninstall_osxfuse.app/Contents/Resources/Scripts/uninstall_osxfuse.sh
|
---|
274 | fi
|
---|
275 |
|
---|
276 | my_rc=0
|
---|
277 | for kext in "${my_kexts[@]}"; do
|
---|
278 | echo unloading $kext
|
---|
279 | /usr/bin/sudo -p "Please enter %u's password (unloading $kext):" /sbin/kextunload -m $kext
|
---|
280 | my_rc2=$?
|
---|
281 | if test "$my_rc2" -ne 0; then
|
---|
282 | echo "An error occurred durning 'sudo /sbin/kextunload -m $kext', there should be a message above. (rc=$my_rc2)"
|
---|
283 | test -x /usr/bin/sudo || echo "warning: Cannot find /usr/bin/sudo or it's not an executable."
|
---|
284 | test -x /sbin/kextunload || echo "warning: Cannot find /sbin/kextunload or it's not an executable"
|
---|
285 | my_rc=$my_rc2
|
---|
286 | fi
|
---|
287 | done
|
---|
288 | if test "$my_rc" -eq 0; then
|
---|
289 | echo "Successfully unloaded VirtualBox kernel extensions."
|
---|
290 | else
|
---|
291 | echo "Failed to unload one or more KEXTs, please reboot the machine to complete the uninstall."
|
---|
292 | test "$my_default_prompt" != "Yes" && read -p "Press <ENTER> to exit"
|
---|
293 | exit 1;
|
---|
294 | fi
|
---|
295 |
|
---|
296 | # Cleaning up pkgutil database
|
---|
297 | for my_pkg in $my_pkgs; do
|
---|
298 | /usr/bin/sudo -p "Please enter %u's password (removing $my_pkg):" /usr/sbin/pkgutil --forget "$my_pkg"
|
---|
299 | done
|
---|
300 |
|
---|
301 | echo "Done."
|
---|
302 | exit 0;
|
---|
303 |
|
---|