-
-
Save thegranddesign/fef254a615c6d1bf67f83c176da8869d to your computer and use it in GitHub Desktop.
Updater For macOS Launch Services
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
### | |
### bisect - Helps troubleshoot disabled services to track down the one that is | |
### causing offense. | |
### | |
### Description | |
### ================================================================================ | |
### | |
### While striving to minimize CPU and memory usage, maximize privacy, and reduce | |
### possible surface area of attacks, many users wish to disable unused or uneeded | |
### services. | |
### | |
### Unfortunately removing some of these services can cause undesirable behavior. | |
### Some of which may not be known immediately after the initial attempt to disable | |
### them. | |
### | |
### On top of that, newer versions of macOS do not allow the user to modify these | |
### services while the OS is running normally and therefore the user must restart | |
### their system for it to take effect. | |
### | |
### For all these reasons and more, having an efficient way to track down offending | |
### services is very important. That's what this script aims to do. | |
### | |
### The user will initially run `bisect.sh start` (see full usages below) and the | |
### script will create a temporary 'holding file' containing which services it | |
### disabled. | |
### | |
### After each run the user will restart their system to test. Regardless of | |
### whether the desirable behavior is witness, the user will restart again back into | |
### recovery mode and rerun this script either as `bisect.sh good` or `bisect.sh | |
### bad` depending on whether the behavior still works as anticipated or not. | |
### | |
### The user will continue doing this until eventually the script narrows down the | |
### offending service to a single possibility. | |
### | |
### Note On Mounting Filesystem | |
### ================================================================================ | |
### | |
### * See `update.sh help` | |
### | |
### Agent/Daemon List File Format | |
### ================================================================================ | |
### | |
### * See `update.sh help` | |
### | |
### Prerequisites | |
### ================================================================================ | |
### | |
### * Filesystem mounted in Read/Write mode (see above) | |
### | |
### * A file containing *all* of the possible agents/daemons you would like to | |
### eventually disable (see format below) | |
### | |
### * The file should be named `launch_<launch_type>.txt` and should be in the same | |
### directory as this script. | |
### | |
### -------------------------------------------------------------------------------- | |
### | |
### Usage: | |
### ./bisect.sh start <launch_type> <system_volume> | |
### | |
### Description: | |
### Starts a new bisect session. This will discard the old session with no | |
### warning. | |
### | |
### Options: | |
### <launch_type> Should be either `agents` or `daemons` | |
### <system_volume> The path to the volume the system resides on | |
### (eg `/Volumes/Macintosh\ HD`) | |
### | |
### Usage: | |
### ./bisect.sh good <launch_type> <system_volume> | |
### | |
### Description: | |
### Tells bisect that the services it disabled last time didn't cause any issues. | |
### It will pick new ones to test. | |
### | |
### Options: | |
### <launch_type> Should be either `agents` or `daemons` | |
### <system_volume> The path to the volume the system resides on | |
### (eg `/Volumes/Macintosh\ HD`) | |
### | |
### Usage: | |
### ./bisect.sh bad <launch_type> <system_volume> | |
### | |
### Description: | |
### Tells bisect that one or more of the services it disabled last time caused a | |
### problem. It will: | |
### | |
### * Re-enable all the services it disabled in the previous run | |
### * Disable one or more of those services | |
### | |
### Options: | |
### <launch_type> Should be either `agents` or `daemons` | |
### <system_volume> The path to the volume the system resides on | |
### (eg `/Volumes/Macintosh\ HD`) | |
### | |
set -euo pipefail | |
_sin_bisect_start() { | |
launch_type="$1" | |
system_volume="$2" | |
script_directory="$("${system_volume}/usr/bin/dirname" "${BASH_SOURCE[0]}")" | |
launch_type_capitalized="$(tr '[:lower:]' '[:upper:]' <<< "${launch_type:0:1}")${launch_type:1}" | |
launch_filename="${script_directory}/launch_${launch_type}.txt" | |
temp_filename="${script_directory}/bisect.temp" | |
bisect_filename="${script_directory}/bisect.txt" | |
echo "Before running a bisection, you should make sure that you are starting" | |
echo "with all services _enabled._" | |
echo "" | |
echo "In order to do this, we will now remove the .bak extension from all" | |
echo "Launch${launch_type_capitalized} files." | |
echo "" | |
echo "Press any key to continue... " | |
"${system_volume}/usr/bin/read" -n 1 -s -r | |
echo "" | |
IFS=$'\n' | |
# shellcheck disable=SC2044 | |
for filename in $(find "${system_volume}/System/Library/Launch${launch_type_capitalized}" -maxdepth 1 -name '*.bak'); do | |
echo " * '${filename%.bak}'" | |
mv "${filename}" "${filename%.bak}" | |
done | |
IFS=' ' | |
echo "" | |
echo " * Copying Fresh Bisection File..." | |
cp -f "${launch_filename}" "${temp_filename}" | |
echo " * Sanitizing Bisection File..." | |
"${system_volume}/usr/bin/sed" '/^#/d' "${temp_filename}" > "${temp_filename}2" | |
"${system_volume}/usr/bin/sed" '/^$/d' "${temp_filename}2" > "${temp_filename}" | |
"${system_volume}/usr/bin/sort" -u --output="${temp_filename}" "${temp_filename}" | |
rm -f "${temp_filename}2" | |
echo " * Creating Initial Bisect Split..." | |
_sin_split_file "${system_volume}" "${temp_filename}" "${bisect_filename}" | |
echo " * Running Initial Service Update..." | |
echo "" | |
"${script_directory}/update.sh" "${launch_type}" "disable" "${system_volume}" "${bisect_filename}" | |
rm -f "${temp_filename}" | |
echo "" | |
echo "You can now reboot and test the bisection..." | |
echo "" | |
} | |
_sin_bisect_good() { | |
launch_type="$1" | |
system_volume="$2" | |
script_directory="$("${system_volume}/usr/bin/dirname" "${BASH_SOURCE[0]}")" | |
launch_type_capitalized="$(tr '[:lower:]' '[:upper:]' <<< "${launch_type:0:1}")${launch_type:1}" | |
temp_filename="${script_directory}/bisect.temp" | |
bisect_filename="${script_directory}/bisect.txt" | |
! [ -e "${bisect_filename}" ] && echo "Can't find an existing bisect file. Run 'bisect start'." && exit 1 | |
echo " * Updating Bisection File..." | |
"${system_volume}/usr/bin/grep" '^# ' "${bisect_filename}" | "${system_volume}/usr/bin/sed" 's/^# //' > "${temp_filename}" | |
_sin_knows_offending_service "${temp_filename}" "${system_volume}" && exit 0 | |
echo " * Calculating Bisect Split..." | |
_sin_split_file "${system_volume}" "${temp_filename}" "${bisect_filename}" | |
echo " * Running Bisection..." | |
echo "" | |
"${script_directory}/update.sh" "${launch_type}" "disable" "${system_volume}" "${bisect_filename}" | |
rm -f "${temp_filename}" | |
echo "" | |
echo "You can now reboot and test the bisection..." | |
echo "" | |
} | |
_sin_bisect_bad() { | |
launch_type="$1" | |
system_volume="$2" | |
script_directory="$("${system_volume}/usr/bin/dirname" "${BASH_SOURCE[0]}")" | |
launch_type_capitalized="$(tr '[:lower:]' '[:upper:]' <<< "${launch_type:0:1}")${launch_type:1}" | |
temp_filename="${script_directory}/bisect.temp" | |
bisect_filename="${script_directory}/bisect.txt" | |
! [ -e "${bisect_filename}" ] && echo "Can't find an existing bisect file. Run 'bisect start'." && exit 1 | |
echo " * Updating Bisection File..." | |
"${system_volume}/usr/bin/grep" --invert-match '^# ' "${bisect_filename}" > "${temp_filename}" | |
echo " * Re-Enabling All Possible Responsible ${launch_type_capitalized}..." | |
echo "" | |
"${script_directory}/update.sh" "${launch_type}" "enable" "${system_volume}" "${temp_filename}" | |
_sin_knows_offending_service "${temp_filename}" "${system_volume}" && exit 0 | |
echo "" | |
echo " * Calculating Bisect Split..." | |
_sin_split_file "${system_volume}" "${temp_filename}" "${bisect_filename}" | |
echo " * Running Bisection..." | |
echo "" | |
"${script_directory}/update.sh" "${launch_type}" "disable" "${system_volume}" "${bisect_filename}" | |
rm -f "${temp_filename}" | |
echo "" | |
echo "You can now reboot and test the bisection..." | |
echo "" | |
} | |
_sin_bisect_reset() { | |
system_volume="$1" | |
script_directory="$("${system_volume}/usr/bin/dirname" "${BASH_SOURCE[0]}")" | |
rm -f "bisect.txt" | |
rm -f "bisect.temp" | |
return 0 | |
} | |
_sin_split_file() { | |
system_volume="$1" | |
temp_filename="$2" | |
bisect_filename="$3" | |
total_lines="$(_sin_total_lines_in_file "${temp_filename}" "${system_volume}")" | |
head_lines="$((total_lines / 2))" | |
tail_lines="$((total_lines - head_lines))" | |
"${system_volume}/usr/bin/head" -n "${head_lines}" "${temp_filename}" > "${bisect_filename}" | |
"${system_volume}/usr/bin/tail" -n "${tail_lines}" "${temp_filename}" | "${system_volume}/usr/bin/sed" 's/^/# /' >> "${bisect_filename}" | |
} | |
_sin_knows_offending_service() { | |
local filename="$1" | |
local system_volume="$2" | |
if [[ "$(_sin_total_lines_in_file "${temp_filename}" "${system_volume}")" == "1" ]]; then | |
echo "" | |
echo "We have determined the offending agent/daemon to be:" | |
echo "" | |
cat "${temp_filename}" | |
echo "" | |
_sin_bisect_reset "${system_volume}" | |
exit 0 | |
else | |
return 1 | |
fi | |
} | |
_sin_total_lines_in_file() { | |
local filename="$1" | |
local system_volume="$2" | |
# shellcheck disable=SC2016 | |
"${system_volume}/usr/bin/wc" -l "${filename}" | "${system_volume}/usr/bin/awk" '{print $1}' | |
} | |
subcommand="${1:-}"; | |
[ "$#" -gt 0 ] && shift 1; | |
case "${subcommand}" in | |
start) | |
_sin_bisect_start "$@" | |
;; | |
reset|stop) | |
_sin_bisect_reset "$@" | |
;; | |
good) | |
_sin_bisect_good "$@" | |
;; | |
bad) | |
_sin_bisect_bad "$@" | |
;; | |
help) | |
sed -rn 's/^### ?//;T;p' "$0" | |
;; | |
*) | |
echo "I don't understand the command '${subcommand}'" | |
;; | |
esac |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
################################################################################ | |
# PROBLEMATIC AGENTS | |
# | |
# Will Freeze Edit Menus | |
# com.apple.speech.speechdatainstallerd | |
# com.apple.speech.speechsynthesisd | |
# com.apple.speech.synthesisserver | |
# | |
# Will Prevent Saving Prompt From Being Shown | |
# com.apple.bird | |
# | |
# Required For Sandboxed Applications To Track Files (This Is Not Related To Web Bookmarks) | |
# com.apple.scopedbookmarkagent.xpc | |
# | |
# Prevents Auto-Refresh Of Calendars | |
# com.apple.CalendarAgent | |
# | |
# Stops Photo Analysis | |
# com.apple.photoanalysisd | |
# | |
################################################################################ | |
# iCloud | |
# | |
com.apple.cloudd | |
com.apple.cloudpaird | |
com.apple.cloudphotod | |
com.apple.followupd | |
com.apple.iCloudUserNotifications | |
com.apple.icloud.findmydeviced.findmydevice-user-agent | |
com.apple.icloud.fmfd | |
com.apple.icloud.searchpartyuseragent | |
com.apple.protectedcloudstorage.protectedcloudkeysyncing | |
com.apple.security.cloudkeychainproxy3 | |
################################################################################ | |
# Safari | |
# | |
com.apple.Safari.SafeBrowsing.Service | |
com.apple.SafariBookmarksSyncAgent | |
com.apple.SafariCloudHistoryPushAgent | |
com.apple.SafariHistoryServiceAgent | |
com.apple.SafariLaunchAgent | |
com.apple.SafariNotificationAgent | |
com.apple.SafariPlugInUpdateNotifier | |
com.apple.WebKit.PluginAgent | |
com.apple.swcd | |
com.apple.webinspectord | |
################################################################################ | |
# iMessage / Facetime | |
# | |
com.apple.avconferenced | |
com.apple.imagent | |
com.apple.imautomatichistorydeletionagent | |
com.apple.imklaunchagent | |
com.apple.imtransferagent | |
################################################################################ | |
# Game Center / Passbook / Apple TV / Homekit | |
# | |
com.apple.CommCenter-osx | |
com.apple.Maps.pushdaemon | |
com.apple.gamed | |
com.apple.homed | |
com.apple.passd | |
com.apple.videosubscriptionsd | |
################################################################################ | |
# Ad-Related | |
# | |
com.apple.ap.adprivacyd | |
com.apple.ap.adservicesd | |
################################################################################ | |
# Screensharing | |
# | |
com.apple.screensharing.MessagesAgent | |
com.apple.screensharing.agent | |
com.apple.screensharing.menuextra | |
################################################################################ | |
# Siri | |
# | |
com.apple.Siri.agent | |
com.apple.assistant_service | |
com.apple.assistantd | |
com.apple.parsec-fbf | |
com.apple.siri-distributed-evaluation | |
com.apple.siri.context.service | |
com.apple.siriknowledged | |
################################################################################ | |
# VoiceOver / Accessibility | |
# | |
com.apple.ScreenReaderUIServer | |
com.apple.VoiceOver | |
com.apple.accessibility.AXVisualSupportAgent | |
com.apple.accessibility.MotionTrackingAgent | |
com.apple.accessibility.dfrhud | |
com.apple.accessibility.heard | |
com.apple.scrod | |
com.apple.voicememod | |
################################################################################ | |
# Quicklook | |
# | |
# com.apple.quicklook | |
com.apple.quicklook.ThumbnailsAgent | |
# com.apple.quicklook.ui.helper | |
################################################################################ | |
# Sidecar | |
# | |
com.apple.sidecar-hid-relay | |
com.apple.sidecar-relay | |
################################################################################ | |
# Debugging Process | |
# | |
com.apple.DiagnosticReportCleanup | |
com.apple.ReportCrash | |
com.apple.ReportGPURestart | |
com.apple.ReportPanic | |
com.apple.TrustEvaluationAgent | |
com.apple.spindump_agent | |
################################################################################ | |
# Screentime / Parental Controls | |
# | |
com.apple.ScreenTimeAgent | |
com.apple.UsageTrackingAgent | |
com.apple.familycircled | |
com.apple.familycontrols.useragent | |
com.apple.familynotificationd | |
################################################################################ | |
# Classroom | |
# | |
com.apple.progressd | |
################################################################################ | |
# Others | |
# | |
com.apple.AMPArtworkAgent | |
com.apple.AMPLibraryAgent | |
com.apple.AOSHeartbeat | |
com.apple.AOSPushRelay | |
com.apple.AirPlayUIAgent | |
com.apple.AirPortBaseStationAgent | |
com.apple.CallHistoryPluginHelper | |
com.apple.CallHistorySyncHelper | |
com.apple.EscrowSecurityAlert | |
com.apple.FileProvider | |
com.apple.KeyboardAccessAgent | |
com.apple.ManagedClientAgent.agent | |
com.apple.ManagedClientAgent.enrollagent | |
com.apple.RemoteDesktop | |
com.apple.RemoteUI | |
com.apple.SocialPushAgent | |
com.apple.amp.mediasharingd | |
com.apple.amsaccountsd | |
com.apple.appleseed.seedusaged | |
com.apple.appleseed.seedusaged.postinstall | |
com.apple.appsleepd | |
com.apple.appstoreagent | |
com.apple.askpermissiond | |
com.apple.commerce | |
com.apple.ctkd | |
com.apple.exchange.exchangesyncd | |
com.apple.findmymacmessenger | |
com.apple.helpd | |
com.apple.icdd | |
com.apple.identityservicesd | |
com.apple.java.InstallOnDemand | |
com.apple.keyboardservicesd | |
com.apple.knowledge-agent | |
com.apple.macos.studentd | |
com.apple.mediaanalysisd | |
com.apple.mediaremoteagent | |
com.apple.mobileactivationd | |
com.apple.mobileassetd | |
com.apple.parentalcontrols.check | |
com.apple.parsecd | |
com.apple.podcasts.PodcastContentService | |
com.apple.powerchime | |
com.apple.rapportd-user | |
com.apple.remindd | |
com.apple.routined | |
com.apple.security.keychain-circle-notification | |
com.apple.sharingd | |
com.apple.suggestd | |
com.apple.syncdefaultsd | |
com.apple.telephonyutilities.callservicesd | |
com.apple.touristd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
################################################################################ | |
# iCloud | |
# | |
com.apple.analyticsd | |
com.apple.icloud.findmydeviced | |
################################################################################ | |
# Debugging Process | |
# | |
com.apple.systemstats.analysis | |
com.apple.systemstats.daily | |
com.apple.systemstats.microstackshot_periodic | |
################################################################################ | |
# Others | |
# | |
# com.apple.ManagedClient Prevents mobileconfig Profiles | |
# com.apple.ManagedClient.enroll Prevents mobileconfig Profiles | |
# com.apple.ManagedClient.startup Prevents mobileconfig Profiles | |
com.apple.AirPlayXPCHelper | |
com.apple.AssetCacheLocatorService | |
com.apple.ManagedClient.cloudconfigurationd | |
com.apple.ManagedClient.mechanism | |
com.apple.RFBEventHelper | |
com.apple.RemoteDesktop.PrivilegeProxy | |
com.apple.SubmitDiagInfo | |
com.apple.appleseed.fbahelperd | |
com.apple.appstored | |
com.apple.apsd | |
com.apple.captiveagent | |
com.apple.commerced | |
com.apple.eapolcfg_auth | |
com.apple.efax | |
com.apple.locate | |
com.apple.locationd | |
com.apple.mediaremoted | |
com.apple.netbiosd | |
com.apple.nis.ypbind | |
com.apple.preferences.timezone.admintool | |
com.apple.rapportd | |
com.apple.remotepairtool | |
com.apple.rtcreportingd | |
com.apple.screensharing | |
com.apple.security.FDERecoveryAgent | |
com.apple.webdavfs_load_kext |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
### | |
### update - Allows files containing a list of services to either be enabled or | |
### disabled. | |
### | |
### Description | |
### ================================================================================ | |
### | |
### While striving to minimize CPU and memory usage, maximize privacy, and reduce | |
### possible surface area of attacks, many users wish to disable unused or uneeded | |
### services. | |
### | |
### In order to make this as painless as possible, this script provides a way to | |
### standardize enabling and disabling those services as well as handling the most | |
### common types of errors that may arise during that process. | |
### | |
### Note On Mounting Filesystem | |
### ================================================================================ | |
### | |
### This script was designed to work with the tools available on a fresh macOS | |
### installation. All applicable commands are prefixed with the mounted volume path | |
### which will need to be mounted with read/write access prior to running this | |
### script. | |
### | |
### From Catalina onwards, this means that you: | |
### | |
### * Boot into recovery mode | |
### * Open Disk Utility | |
### * Mount your system volume | |
### * Close Disk Utility | |
### | |
### Once that's completed, you'll need to open Terminal (Utilities -> Terminal) and | |
### navigate to the location where this script lives. | |
### | |
### Agent/Daemon List File Format | |
### ================================================================================ | |
### | |
### * Lines beginning with `#` are considered comments and are ignored | |
### * Lines should contain *only* the domain portion of the agent filename. | |
### | |
### Valid Items: | |
### | |
### com.apple.security.keychain-circle-notification | |
### com.apple.sharingd | |
### | |
### Invalid Items: | |
### | |
### /System/Library/LaunchAgents/com.apple.sharingd.plist | |
### com.apple.sharingd.plist | |
### com.apple.* | |
### | |
### Prerequisites | |
### ================================================================================ | |
### | |
### * Filesystem mounted in Read/Write mode (see above) | |
### | |
### * A file containing *all* of the possible agents/daemons you would like to | |
### eventually disable (see format below) | |
### | |
### * The file should be named `launch_<launch_type>.txt` and should be in the same | |
### directory as this script. | |
### | |
### References | |
### ================================================================================ | |
### | |
### * https://gist.github.com/pwnsdx/1217727ca57de2dd2a372afdd7a0fc21 | |
### | |
### -------------------------------------------------------------------------------- | |
### | |
### Usage: | |
### ./update.sh all <action> <system_volume> | |
### | |
### Description: | |
### Either enables or disables all services listed in the list files. | |
### | |
### Options: | |
### <action> Should be either `enable` or `disable` | |
### <system_volume> The path to the volume the system resides on | |
### (eg `/Volumes/Macintosh\ HD`) | |
### | |
### Usage: | |
### ./update.sh agents <action> <system_volume> | |
### | |
### Description: | |
### Either enables or disables all agents listed in the agent list file. | |
### | |
### Options: | |
### <action> Should be either `enable` or `disable` | |
### <system_volume> The path to the volume the system resides on | |
### (eg `/Volumes/Macintosh\ HD`) | |
### | |
### Usage: | |
### ./update.sh daemons <action> <system_volume> | |
### | |
### Description: | |
### Either enables or disables all daemons listed in the daemon list file. | |
### | |
### Options: | |
### <action> Should be either `enable` or `disable` | |
### <system_volume> The path to the volume the system resides on | |
### (eg `/Volumes/Macintosh\ HD`) | |
### | |
set -euo pipefail | |
_sin_update_all() { | |
action="$1" | |
system_volume="$2" | |
_sin_update "agents" "${action}" "${system_volume}" | |
_sin_update "daemons" "${action}" "${system_volume}" | |
} | |
_sin_update() { | |
launch_type="$1" | |
action="$2" | |
system_volume="$3" | |
script_directory="$("${system_volume}/usr/bin/dirname" "${BASH_SOURCE[0]}")" | |
list_filename="${4:-"${script_directory}/launch_${launch_type}.txt"}"; | |
_sin_run_update "${action}" "${launch_type}" "${list_filename}" "${system_volume}" | |
} | |
_sin_run_update() { | |
action="$1" | |
launch_type="$2" | |
list_filename="$3" | |
system_volume="$4" | |
[ -z "${action}" ] && echo "Missing action: '${action}'" && exit 1 | |
[ -z "${launch_type}" ] && echo "Missing launch_type: '${launch_type}'" && exit 1 | |
[ -z "${list_filename}" ] && echo "Missing list_filename: '${list_filename}'" && exit 1 | |
[ -z "${system_volume}" ] && echo "Missing system_volume: '${system_volume}'" && exit 1 | |
IFS=$'\n' | |
# shellcheck disable=SC2013 | |
for agent in $(sed '/^#/d' "${list_filename}" | sed '/^$/d' | sort -u); do | |
enabled_filename="${system_volume}/System/Library/Launch${launch_type}/${agent}.plist" | |
disabled_filename="${system_volume}/System/Library/Launch${launch_type}/${agent}.plist.bak" | |
file_status="" | |
if [[ "${action}" == "enable" ]]; then | |
source_filename="${disabled_filename}" | |
destination_filename="${enabled_filename}" | |
elif [[ "${action}" == "disable" ]]; then | |
source_filename="${enabled_filename}" | |
destination_filename="${disabled_filename}" | |
else | |
echo "Invalid Action: '${action}'" | |
exit 1 | |
fi | |
if [ -e "${destination_filename}" ]; then | |
file_status="[EXISTS ]" | |
elif ! [ -e "${source_filename}" ] && ! [ -h "${source_filename}" ]; then | |
file_status="[MISSING]" | |
elif mv "${source_filename}" "${destination_filename}" 2> /dev/null; then | |
file_status="[OK ]" | |
else | |
file_status="[ERROR ]" | |
fi | |
echo -e "${file_status} ${launch_type}\t'${agent}'" | |
done | |
} | |
subcommand="${1:-}"; | |
[ "$#" -gt 0 ] && shift 1; | |
case "${subcommand}" in | |
all) | |
_sin_update_all "$@" | |
;; | |
agents) | |
_sin_update "Agents" "$@" | |
;; | |
daemons) | |
_sin_update "Daemons" "$@" | |
;; | |
help) | |
sed -rn 's/^### ?//;T;p' "$0" | |
;; | |
*) | |
echo "I don't understand the command '${subcommand}'" | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
One-liners for those who might be interested: