-
Notifications
You must be signed in to change notification settings - Fork 0
/
App-Auto-Patch-via-Dialog-Nitor.zsh
executable file
·2159 lines (1741 loc) · 93.7 KB
/
App-Auto-Patch-via-Dialog-Nitor.zsh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/zsh --no-rcs
####################################################################################################
#
# App Auto-Patch via swiftDialog
#
####################################################################################################
#
# HISTORY
#
# Version 2.0.0, 12.19.2023 Robert Schroeder (@robjschroeder)
# - **Breaking Change** for users of App Auto-Patch before `2.0.0`
# - Removed the unattendExit variable out of Jamf Pro Script parameters, this is now under the ### Unattended Exit Options ###
# - Moved the outdatedOsAction variable from Parameter 9 to Parameter 10 in Jamf Pro Script parameters
# - Script cleanup and organization
# - dialogInstall function called only if interactiveMode is greater than 0
# - Added logic for AAP-Activator (thanks @TechTrekkie)
# - Variable added for AAP-Activator logic under ### Deferral Options ###, please see documentation for more information
# - Added optionalLabels array. Installomator labels listed in this array will first check to see if the app is installed. If installed, AAP will write the label to the required array. If the app is not installed, it will get skipped.
#
# Version 2.0.1, 12.20.2023 Robert Schroeder (@robjschroeder)
# - **Breaking Change** for users of App Auto-Patch before `2.0.1`
# - Removed the scriptLog variable out of Jamf Pro Script parameters, this is now under the ### Script Log and General Behavior Options ###
# - Removed the debugMode variable out of Jamf Pro Script parameters, this is now under the ### Script Log and General Behavior Options ###
# - Removed the outdatedOSAction variable out of the Jamf Pro Script parameters, this is now under the ### Script Log and General Behavior Options ###
# - Removed the useOverlayIcon variable out of the Jamf Pro Script parameters, this is now under ### Overlay Icon ### in the Custom Branding, Overlay Icon, etc section
# - Fixed issue with labels (#13), improving how regex handles app labels from Installomator
# - Updated AAP Activator Flag to pull from config plist and automatically determine if being executed by AAP-Activator (thanks @TechTrekkie)
# - Updated deferral reset logic to only update if maxDeferrals is not Disabled. Reset deferrals if remaining is higher than max (thanks @TechTrekkie)
# - Updated deferral workflow to run removeInstallomator and quitScript triggers to mirror non-deferral workflow (thanks @TechTrekkie)
# - Created installomatorOptions Parameter, which can be used to overwrite default installomator options
# - Fixed Installomator appNewVersion curl URL
# - Changed `removeInstallomator` default to false, this will keep AAP's Installomator folder present until Installomator has an update
#
# Version 2.0.2, 01.02.2024 Robert Schroeder (@robjschroeder)
# - **Breaking Change** for users of App Auto-Patch before `2.0.2`
# - Check Jamf Pro Script Parameters before deploying version 2.0.1, we have re-organized them
# - Replaced logic of checking app version for discovered apps
# - Reduced output to logs outside of debug modes (thanks @dan-snelson)
#
# Version 2.0.3, 01.02.2024 Robert Schroeder (@robjschroeder)
# - App Auto-Patch will do an additional check with a debug version of Installomator to determine if an application that is installed needs an update
#
# Version 2.0.4, 01.03.2024 Andrew Spokes (@TechTrekkie)
# - Adjusting references of 'There is no newer version available' to 'same as installed' to fix debug check behavior for DMG/ZIP installomator labels
#
# Version 2.0.5, 01.05.2024 Robert Schroeder (@robjschroeder)
# - If `interactiveMode` is greater than 1 (set for Full Interactive), and AAP does not detect any app updates a dialog will be presented to the user letting them know.
#
# Version 2.0.6, 01.22.2024 Robert Schroeder (@robjschroeder)
# - New feature, `convertAppsInHomeFolder`. If this variable is set to `true` and an app is found within the /Users/* directory, the app will be queued for installation into the default path and removed into from the /Users/* directory
# - New feature, `ignoreAppsInHomeFolder`. If this variable is set to `true` apps found within the /Users/* directory will be ignored. If `false` an app discovered with an update will be queued and installed into the default directory. This may may lead to two version of the same app installed. (thanks @gilburns!)
#
# Version 2.0.7, 01.22.2024, Robert Schroeder (@robjschroeder)
# - Added function to list application names needing to update to show users before updates are installed during the deferral window (thanks @AndrewMBarnett)
# - Added text to explain the deferral timer during the deferral window
# - Text displayed during the deferral period and no deferrals remaining changes depending on how many deferrals are left.
# - Deferral window infobox text is now dynamic based on `deferralTimerAction`
# - Adjusted size of deferral window based on deferrals remaining (thanks @TechTrekkie)
#
# Version 2.0.8, 01.24.2024
# - Fixed helpMessage variable for the deferral window so the helpmessage displays properly
# - Added application list to deferral window when 0 deferrals remain to mirror behavior when deferrals greater than 0
# - Updated infobox text to indicate "Updates will automatically install after the timer expires" when 0 deferrals remain
#
# Version 2.8.1, 01.26.2024, Andrew Spokes (@TechTrekkie)
# - Fixed the --moveable flags spelling so the dialog will be set to moveable properly
#
# Version 2.9.0, 02.08.2024, Robert Schroeder (@robjschroeder)
# - Updated minimum swiftDialog minimum to 2.4.0 (thanks @AndrewMBarnett)
# - Added Teams and Slack webhook messaging functionality (thanks @AndrewMBarnett and @TechTrekkie)
# - Use the `webhookEnabled` variable and webhook URLs to set this functionality
# - Function for finding Jamf Pro URL for the computer running AAP (thanks @AndrewMBarnett and @TechTrekkie)
# - Added minimize windowbutton to let windows run and minimize to applicable dialogs
# - Added script version number to help message (thanks @dan-snelson)
#
# Version 2.9.1, 02.14.2024, Robert Schroeder (@robjschroeder)
# - Fixed issue where compact list style was being used during update progress and increased font size
# - The analyzing Apps window now shows app logos during discovery (thanks @dan-snelson)
# - Removed all notes from script history previous to version 2.0.0, see changelog to reference any prior changes.
# - Updated jamfProComputerURL variable to a search by serial vs. running a recon to get JSS ID, an extra click but saves a recon (thanks @dan-snelson)
# - Removed minimize windowbutton from the deferral dialog to avoid confusion from users mistakenly hiding the dialog (Thanks @TechTrekkie)
# - Updated webhook JSON to utilize appTitle variable vs. direct App Auto-Patch name (thanks @Tech-Trekkie)
#
# Version 2.9.2, 02.15.2024, Robert Schroeder (@robjschroeder)
# - Fixed an issue that would cause a blank list to appear in the patching dialog if `runDiscovery` was set to `false`, a placeholder will be used for now
# ** This issue was introduced in version 2.9.1 ** Issue #59
#
# Version 2.9.3, 02.17.2024, Robert Schroeder (@robjschroeder)
# - An added case for on-prem, multi-node, or clustered environments (thanks @dan-snelson)
# - Webhook logic now uses case statements for evaluation (thanks @dan-snelson)
# - Improved webhook messaging (thanks @dan-snelson)
# - Improved infobox information for patching dialog (thanks @dan-snelson)
#
# Version 2.9.4, 03.07.2024, Andrew Barnett (@AndrewMBarnett)
# - Added functionality for icons to show up in the deferral window and installing/updating window before they are processing (thanks @AndrewMBarnett)
#
# Version 2.9.5, 03.07.2024, Andrew Spokes (@TechTrekkie)
# - Added logic to display AAP Logo for the App Icon if the app does not exist (thanks @TechTrekkie)
#
# Version 2.9.6, 03.15.2024, Robert Schroeder (@robjschroeder)
# - Added `--no-rcs` to shebang of script. This addresses CVE-2024-27301. https://nvd.nist.gov/vuln/detail/CVE-2024-27301/change-record?changeRecordedOn=03/14/2024T15:15:50.680-0400
#
# Version 2.9.7, 03.19.2024, Robert Schroeder (@robjschroeder)
# - Added a new options flag, `useLatestAvailableInstallomatorScriptVersion`. If set to true, AAP will validate the VERSIONDATE from the latest Installomator script and will replace if they don't match. If `false` only Release version of Installomator will be used for comparision.
#
# Version 2.10.0, 03.20.2024, Andrew Spokes (@TechTrekkie)
# - Merged AAP Activator functionality into main AAP Sript. Activator (Deferral Workflow) will execute if maxDeferrals is set to an integer. Disabled will execute "On-Demand" workflow
# - Added Activator/Deferral Workflow variables:
# - daysUntilReset = The number of days until the Activator/Deferral Workflow resets the patching status to false (ex: 7 days resets weekly)
# - patchWeekStartDay = Day of the week to set the start date for weekly patching/daysUntilReset count (1=Mon 2=Tue...7=Sun), leave blank to disable
# - maxDisplayAssertionCount = The maximum number of deferred attempts from Display Assertions (integer, leave blank to disable)
# - New Variable = selfServicePatchingStatusModeReset - Determins if the weekly patching status should be set to True when running in "On-Demand/Self Service" mode (when deferrals are disabled) [1=Never, 2=Always, 3=On Success (no errors)]
# - New Variable = ignoreDNDApps - Comma separated list of app names to ignore when evaluating DND/Display Assertions (ex: ignoreDNDApps="firefox,Google Chrome,caffeinate")
# - Consolidated AppAutoPatchDeferrals config file into AppAutoPatchStatus config file - Any existing Extension Attributes will need to be updated
# - Moved Caffeinate function to run after Activator/Deferral Workflow to not be included as a false positive display assertion
#
# Version 2.11.0, 03.25.2024, Andrew Spokes (@TechTrekkie)
# - Added AAPPatchingCompleteDate to PLIST to populate the last date/time patching was completed for a device. Added new EA to pull this value
# - Fixed an issue where debug Installomator may not be applied. (@robjschroeder)
#
# Version 2.11.1, 05.25.2024, Andrew Spokes (@TechTrekkie)
# - Added BLOCKING_PROCESS_ACTION="ignore" to the installomator test when populating option labels. Without this the script was prompting users to quit some apps during the discovery phase for optional labels.
#
####################################################################################################
####################################################################################################
#
# Global Variables
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Script Version and Jamf Pro Script Parameters
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
scriptVersion="2.11.1"
scriptFunctionalName="App Auto-Patch"
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
interactiveMode="${4:="1"}" # Parameter 4: Interactive Mode [ 0 (Completely Silent) | 1 (Silent Discovery, Interactive Patching) | 2 (Full Interactive) (default) ]
ignoredLabels="${5:="*"}" # Parameter 5: A space-separated list of Installomator labels to ignore (i.e., "microsoft* googlechrome* jamfconnect zoom* 1password* firefox* swiftdialog")
requiredLabels="${6:=""}" # Parameter 6: A space-separated list of required Installomator labels (i.e., "firefoxpkg_intl")
optionalLabels="${7:=""}" # Parameter 7: A space-separated list of optional Installomator labels (i.e., "renew") ** Does not support wildcards **
installomatorOptions="${8:-""}" # Parameter 8: A space-separated list of options to override default Installomator options (i.e., BLOCKING_PROCESS_ACTION=prompt_user NOTIFY=silent LOGO=appstore)
maxDeferrals="${9:-"5"}" # Parameter 9: Number of times a user is allowed to defer before being forced to install updates. A value of "Disabled" will not display the deferral prompt. [ `integer` | Disabled (default) ]
# Nitor: Only update given apps
includedLabels="${10:=" vlc zoom zoomclient zoomgov zoomoutlookplugin zoomoutlookpluginremoval zoomroom firefox firefox_da firefox_intl firefoxdeveloperedition firefoxesr firefoxesr_intl firefoxpkg firefoxpkg_intl googlechrome googlechromepkg googlechromeenterprise googlechromedmg jetbrainsintellijidea "}"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Various Feature Variables
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
### Script Log and General Behavior Options ###
scriptLog="/var/log/com.company.log" # Script Log Location [ /var/log/com.company.log ] (i.e., Your organization's default location for client-side logs)
debugMode="false" # Debug Mode [ true | false (default) | verbose ] Verbose adds additional logging, debug turns Installomator script to DEBUG 2, false for production
outdatedOsAction="/System/Library/CoreServices/Software Update.app" # Outdated OS Action [ /System/Library/CoreServices/Software Update.app (default) | jamfselfservice://content?entity=policy&id=117&action=view ] (i.e., Jamf Pro Self Service policy ID for operating system upgrades)
### swiftDialog Options ###
swiftDialogMinimumRequiredVersion="2.4.0" # Minimum version of swiftDialog required to use workflow
### Deferral Options ###
deferralTimer=3600 # Time given to the user to respond to deferral prompt if enabled
deferralTimerAction="Defer" # What happens when the deferral timer expires [ Defer | Continue ]
daysUntilReset=3 # The number of days until the activator resets the patching status to False
patchWeekStartDay="" # Patch Week Start Day of Week (1-7, blank to disable): The day of week to set the start date for weekly patching: (1=Mon 2=Tue...7=Sun)
maxDisplayAssertionCount="" # The maximum number of deferred attempts from Display Assertions (Integer, blank to disable)
selfServicePatchingStatusModeReset="1" # Determines if weekly patching status should be set to true when running in Self Service mode (deferrals disabled) [1=Never, 2=Always, 3=On Success (no errors)]
ignoreDNDApps="" # Comma separated list of app names to ignore when evaluating DND (ex: ignoreDNDApps="firefox,Google Chrome,Safari,Amphetamine,caffeinate")
### Unattended Exit Options ###
unattendedExit="false" # Unattended Exit [ true | false (default) ]
unattendedExitSeconds="60" # Number of seconds to wait until a kill Dialog command is sent
### App Auto-Patch Path Variables ###
aapPath="/Library/Application Support/AppAutoPatch"
appAutoPatchConfigFile="/Library/Application Support/AppAutoPatch/AppAutoPatch.plist"
appAutoPatchStatusConfigFile="/Library/Application Support/AppAutoPatch/AppAutoPatchStatus.plist"
installomatorPath="/Library/Application Support/AppAutoPatch/Installomator"
installomatorScript="$installomatorPath/Installomator.sh"
fragmentsPath="$installomatorPath/fragments"
### App Auto-Patch Other Behavior Options ###
runDiscovery="true" # Re-run discovery of installed applications [ true (default) | false ]
removeInstallomatorPath="false" # Remove Installomator after App Auto-Patch is completed [ true | false (default) ]
convertAppsInHomeFolder="true" # Remove apps in /Users/* and install them to do default path [ true (default) | false ]
ignoreAppsInHomeFolder="false" # Ignore apps found in '/Users/*'. If an update is found in '/Users/*' and variable is set to `false`, the app will be updated into the application's default path [ true | false (default) ]
useLatestAvailableInstallomatorScriptVersion="true" # Will compare the VERSIONDATE of the local Installomator script against the VERSIONDATE of the latest available on GitHub, if they don't match, AAP will download and replace the local Installomator script with the latest
### Webhook Options ###
webhookEnabled="all" # Enables the webhook feature [ all | failures | false (default) ]
teamsURL="" # Teams webhook URL
slackURL=$SLACK_URL
# Slack webhook URL
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Custom Branding, Overlay Icon, etc
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
### App Title ###
# If you desire to customize `App Auto-Patch` to be named something else
appTitle="App Auto-Patch"
### Desktop/Laptop Icon ###
# Set icon based on whether the Mac is a desktop or laptop
if system_profiler SPPowerDataType | grep -q "Battery Power"; then
icon="SF=laptopcomputer.and.arrow.down,weight=regular,colour1=gray,colour2=red"
else
icon="SF=desktopcomputer.and.arrow.down,weight=regular,colour1=gray,colour2=red"
fi
### Overlay Icon ###
useOverlayIcon="true" # Toggles swiftDialog to use an overlay icon [ true (default) | false ]
# Create `overlayicon` from Self Service's custom icon (thanks, @meschwartz!)
if [[ "$useOverlayIcon" == "true" ]]; then
xxd -p -s 260 "$(defaults read /Library/Preferences/com.jamfsoftware.jamf self_service_app_path)"/Icon$'\r'/..namedfork/rsrc | xxd -r -p > /var/tmp/overlayicon.icns
overlayicon="/var/tmp/overlayicon.icns"
else
overlayicon=""
fi
#Checking for AAPLogo
if [[ ! -e "/Library/Application Support/AppAutoPatch/AAPLogo.png" ]]; then
echo "downloading AAP Logo"
logoImage="https://raw.githubusercontent.com/robjschroeder/App-Auto-Patch/main/Images/AAPLogo.png"
logoImageFileName=$( echo ${logoImage} | awk -F '/' '{print $NF}' )
curl -L --location --silent "$logoImage" -o "/Library/Application Support/AppAutoPatch/${logoImageFileName}"
fi
logoImage="/Library/Application Support/AppAutoPatch/AAPLogo.png"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Operating System, Computer Model Name, etc.
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
computerName=$( scutil --get ComputerName )
osVersion=$( sw_vers -productVersion )
osBuild=$( sw_vers -buildVersion )
osMajorVersion=$( echo "${osVersion}" | awk -F '.' '{print $1}' )
serialNumber=$( ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformSerialNumber/{print $4}' )
modelName=$( /usr/libexec/PlistBuddy -c 'Print :0:_items:0:machine_name' /dev/stdin <<< "$(system_profiler -xml SPHardwareDataType)" )
timestamp="$( date '+%Y-%m-%d-%H%M%S' )"
dialogVersion=$( /usr/local/bin/dialog --version )
exitCode="0"
jamfProURL=$(/usr/bin/defaults read /Library/Preferences/com.jamfsoftware.jamf.plist jss_url)
# Jamf Pro URL for on-prem, multi-node, clustered environments
case ${jamfProURL} in
*"dev"* ) jamfProURL="https://jamfpro-dev.company.com" ;;
*"beta"* ) jamfProURL="https://jamfpro-beta.company.com" ;;
* ) jamfProURL="https://jamfpro-prod.company.com" ;;
esac
jamfProComputerURL="${jamfProURL}/computers.html?query=${serialNumber}&queryType=COMPUTERS"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Deferral Workflow Date Calculations
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
CurrentDate=$(date +"%Y-%m-%d")
CurrentDateEpoch=$(date -j -f "%Y-%m-%d" "$CurrentDate" "+%s")
#### Calculate Patch Week Start Date ####
if [[ $patchWeekStartDay != "" ]]; then
# Get the current day of the week
current_day=$(date +%u)
# Calculate the number of days to subtract to get to the most recent patch week start date
days_to_subtract=$((current_day - $patchWeekStartDay))
if [ $days_to_subtract -lt 0 ]; then
days_to_subtract=$((days_to_subtract + 7))
fi
# Calculate the date of the most recent patch week start date
Patch_Week_Start_Date=$(date -v "-$days_to_subtract"d "+%Y-%m-%d")
else
Patch_Week_Start_Date=$CurrentDate
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# IT Support Variable (thanks, @AndrewMBarnett)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
### Support Team Details ###
supportTeamName="Nitor Systems Administration"
supportTeamPhone="IT Phone Number"
supportTeamEmail="[email protected]"
supportTeamWebsite="https://nitorgroup.slack.com/archives/CPBLB8SSHe"
supportTeamHyperlink="[${supportTeamWebsite}](https://${supportTeamWebsite})"
# Create the help message based on Support Team variables
#helpMessage="If you need assistance, please contact ${supportTeamName}: \n- **Telephone:** ${supportTeamPhone} \n- **Email:** ${supportTeamEmail} \n- **Help Website:** ${supportTeamHyperlink} \n\n**Computer Information:** \n- **Operating System:** $osVersion ($osBuild) \n- **Serial Number:** $serialNumber \n- **Dialog:** $dialogVersion \n- **Started:** $timestamp \n- **Script Version:** $scriptVersion"
helpMessage=If you need assistance, please contact #nsa in Slack at https://nitorgroup.slack.com/archives/CPBLB8SSHe, \n\n**Computer Information:** \n- **Operating System:** $osVersion ($osBuild) \n- **Serial Number:** $serialNumber \n- **Dialog:** $dialogVersion \n- **Started:** $timestamp \n- **Script Version:** $scriptVersion"
####################################################################################################
#
# Pre-flight Checks (thanks, @dan-snelson)
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Client-side Logging
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
if [[ ! -f "${scriptLog}" ]]; then
touch "${scriptLog}"
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Client-side Script Logging Function
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function updateScriptLog() {
echo "${scriptFunctionalName}: $( date +%Y-%m-%d\ %H:%M:%S ) - ${1}" | tee -a "${scriptLog}"
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Path Related Functions
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function makePath() {
mkdir -p "$(sed 's/\(.*\)\/.*/\1/' <<< $1)"
updateScriptLog "Path made: $1"
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Logging Related Functions
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function preFlight() {
updateScriptLog "[PRE-FLIGHT] $1"
}
function notice() {
updateScriptLog "[NOTICE] $1"
}
function debugVerbose() {
if [[ "$debugMode" == "verbose" ]]; then
updateScriptLog "[DEBUG VERBOSE] $1"
fi
}
function debug() {
if [[ "$debugMode" == "true" ]]; then
updateScriptLog "[DEBUG] $1"
fi
}
function infoOut() {
updateScriptLog "[INFO] $1"
}
function errorOut(){
updateScriptLog "[ERROR] $1"
}
function error() {
updateScriptLog "[ERROR] $1"
let errorCount++
}
function warning() {
updateScriptLog "[WARNING] $1"
let errorCount++
}
function fatal() {
updateScriptLog "[FATAL ERROR] $1"
exit 1
}
function quitOut(){
updateScriptLog "[QUIT] $1"
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Current Logged-in User Function
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function currentLoggedInUser() {
loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' )
preFlight "Current Logged-in User: ${loggedInUser}"
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Logging Preamble
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
updateScriptLog "\n\n###\n# ${scriptFunctionalName} (${scriptVersion})\n# https://techitout.xyz/app-auto-patch\n###\n"
preFlight "Initiating …"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Confirm script is running as root
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
if [[ $(id -u) -ne 0 ]]; then
preFlight "This script must be run as root; exiting."
exit 1
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Confirm Dock is running / user is at Desktop
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
until pgrep -q -x "Finder" && pgrep -q -x "Dock"; do
preFlight "Finder & Dock are NOT running; pausing for 1 second"
sleep 1
done
preFlight "Finder & Dock are running; proceeding …"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Validate Logged-in System Accounts
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
preFlight "Check for Logged-in System Accounts …"
currentLoggedInUser
counter="1"
until { [[ "${loggedInUser}" != "_mbsetupuser" ]] || [[ "${counter}" -gt "180" ]]; } && { [[ "${loggedInUser}" != "loginwindow" ]] || [[ "${counter}" -gt "30" ]]; } ; do
preFlight "Logged-in User Counter: ${counter}"
currentLoggedInUser
sleep 2
((counter++))
done
loggedInUserFullname=$( id -F "${loggedInUser}" )
loggedInUserFirstname=$( echo "$loggedInUserFullname" | sed -E 's/^.*, // ; s/([^ ]*).*/\1/' | sed 's/\(.\{25\}\).*/\1…/' | awk '{print ( $0 == toupper($0) ? toupper(substr($0,1,1))substr(tolower($0),2) : toupper(substr($0,1,1))substr($0,2) )}' )
loggedInUserID=$( id -u "${loggedInUser}" )
preFlight "Current Logged-in User First Name: ${loggedInUserFirstname}"
preFlight "Current Logged-in User ID: ${loggedInUserID}"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Validate Operating System Version Monterey or later
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Since swiftDialog and App Auto-Patch require at least macOS 12 Monterey, first confirm the major OS version
if [[ "${osMajorVersion}" -ge 12 ]] ; then
preFlight "macOS ${osMajorVersion} installed; proceeding ..."
else
# The Mac is running an operating system older than macOS 12 Monterey; exit with an error
preFlight "swiftDialog and ${appTitle} require at least macOS 12 Monterey and this Mac is running ${osVersion} (${osBuild}), exiting with an error."
osascript -e 'display dialog "Please advise your Support Representative of the following error:\r\rExpected macOS Monterey (or newer), but found macOS '"${osVersion}"' ('"${osBuild}"').\r\r" with title "'"${scriptFunctionalName}"': Detected Outdated Operating System" buttons {"Open Software Update"} with icon caution'
preFlight "Executing /usr/bin/open '${outdatedOsAction}' …"
su - "${loggedInUser}" -c "/usr/bin/open \"${outdatedOsAction}\""
exit 1
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Ensure the computer does not go to sleep during AAP (thanks, @grahampugh!)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
aapPID="$$"
#Moved this to after the new Activator workflow so it doesn't detect itself as a valid display assertion
#preFlight "Caffeinating this script (PID: $aapPID)"
#caffeinate -dimsu -w $aapPID &
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Validate/install swiftDialog (Thanks big bunches, @acodega!)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function dialogInstall() {
# Get the URL of the latest PKG From the Dialog GitHub repo
dialogURL=$(curl -L --silent --fail "https://api.github.com/repos/swiftDialog/swiftDialog/releases/latest" | awk -F '"' "/browser_download_url/ && /pkg\"/ { print \$4; exit }")
# Expected Team ID of the downloaded PKG
expectedDialogTeamID="PWA5E9TQ59"
preFlight "Installing swiftDialog..."
# Create a temporary working directory
workDirectory=$( basename "$0" )
tempDirectory=$( mktemp -d "/private/tmp/$workDirectory.XXXXXX" )
# Download the installer package
curl --location --silent "$dialogURL" -o "$tempDirectory/Dialog.pkg"
# Verify the download
teamID=$(spctl -a -vv -t install "$tempDirectory/Dialog.pkg" 2>&1 | awk '/origin=/ {print $NF }' | tr -d '()')
# Install the package if Team ID validates
if [[ "$expectedDialogTeamID" == "$teamID" ]]; then
/usr/sbin/installer -pkg "$tempDirectory/Dialog.pkg" -target /
sleep 2
dialogVersion=$( /usr/local/bin/dialog --version )
preFlight "swiftDialog version ${dialogVersion} installed; proceeding..."
else
# Display a so-called "simple" dialog if Team ID fails to validate
osascript -e 'display dialog "Please advise your Support Representative of the following error:\r\r• Dialog Team ID verification failed\r\r" with title "'"${scriptFunctionalName}"': Error" buttons {"Close"} with icon caution'
exitCode="1"
quitScript
fi
# Remove the temporary working directory when done
rm -Rf "$tempDirectory"
}
function dialogCheck() {
# Check for Dialog and install if not found
if [ ! -e "/Library/Application Support/Dialog/Dialog.app" ]; then
preFlight "swiftDialog not found. Installing..."
dialogInstall
else
dialogVersion=$(/usr/local/bin/dialog --version)
if [[ "${dialogVersion}" < "${swiftDialogMinimumRequiredVersion}" ]]; then
preFlight "swiftDialog version ${dialogVersion} found but swiftDialog ${swiftDialogMinimumRequiredVersion} or newer is required; updating..."
dialogInstall
else
preFlight "swiftDialog version ${dialogVersion} found; proceeding..."
fi
fi
}
if [ ${interactiveMode} -gt 0 ]; then
notice "Interactive mode is greater than 0, checking for dialog"
dialogCheck
else
notice "Interactive mode is 0, no need to check for dialog, continuing ... "
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Declare configArray
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
preFlight "Declaring configArray and setting ignoredLabelsArray and requiredLabelsArray"
declare -A configArray=()
ignoredLabelsArray=($(echo ${ignoredLabels}))
requiredLabelsArray=($(echo ${requiredLabels}))
optionalLabelsArray=($(echo ${optionalLabels}))
convertedLabelsArray=($(echo ${convertedLabels}))
# Nitor
includedLabelsArray=($(echo ${includedLabels}))
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Gather Error Log
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
installomatorLogFile="/var/log/Installomator.log"
duplicate_log_dir=$( mktemp -d /var/tmp/InstallomatorErrors.XXXXXX )
marker_file="/var/tmp/Installomator_marker.txt"
chmod 655 "$duplicate_log_dir"
function createMarkerFile(){
if [ ! -f "$marker_file" ]; then
preFlight "Marker file not found, creating temp marker file"
touch "$marker_file"
else
preFlight "marker file exist, continuing"
fi
}
function createLastErrorPosition() {
# Create a timestamp for the current run
timestamp=$(date +%Y%m%d%H%M%S)
preFlight "Current time stamp: $timestamp"
# Create a directory for duplicate log files if it doesn't exist
if [ ! -d "$duplicate_log_dir" ]; then
mkdir -p "$duplicate_log_dir"
preFlight "Creating duplicate log file"
else
preFlight "Duplicate log directory exists, continuing"
fi
# Create a directory for duplicate log files if it doesn't exist
if [ ! -f "$marker_file" ]; then
preFlight "Marker file not found, creating temp marker file"
touch "$marker_file"
else
preFlight "marker file exist, continuing"
fi
# Specify the duplicate log file with a timestamp
duplicate_installomatorLogFile="$duplicate_log_dir/Installomator_error_$timestamp.log"
preFlight "Duplicate Log File location: $duplicate_installomatorLogFile"
# Find the last position marker or start from the beginning if not found
if [ -f "$marker_file" && -f $installomatorLogFile ]; then
lastPosition=$(cat "$marker_file")
else
preFlight "Creating Installomator log file and setting error position as zero"
touch "$installomatorLogFile"
chmod 755 "$installomatorLogFile"
lastPosition=0
fi
# Copy new entries from Installomator.log to the duplicate log file
if [ -f "$installomatorLogFile" ]; then
tail -n +$((lastPosition + 1)) "$installomatorLogFile" > "$duplicate_installomatorLogFile"
preFlight "Installomator log file exists. Tailing new entries from log file to duplicate log file"
else
preFlight "Installomator log file not found. Creating now"
checkInstallomator
fi
# Update the marker file with the new position
wc -l "$installomatorLogFile" | awk '{print $1}' > "$marker_file"
preFlight "Updating marker file"
lastPosition=$(cat "$marker_file")
preFlight "Last position: $lastPosition"
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Checking Last Error Position
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function verifyLastPosition(){
# Find the last position text in scriptLog
lastPosition_line=$(tail -n 400 "$scriptLog" | grep 'Last position:' | tail -n 1)
if [ -n "$lastPosition_line" ]; then
# Extract the last position from the line
lastPosition=$(echo "$lastPosition_line" | awk -F 'Last position:' '{print $2}' | tr -d '[:space:]')
echo "$lastPosition" > "$marker_file"
# Check if last position is less than or equal to zero
if [[ ! -f "{$installomatorLogFile}" ]] || [[ "${lastPosition}" -le 0 ]]; then
preFlight "Last position is less than one or Installomator log doesn't exist. Creating position."
createLastErrorPosition
else
preFlight "Last position is greater than zero and Installomator log file exists. Continuing."
lastPositionUpdated=$(cat "$marker_file")
preFlight "Last position: $lastPositionUpdated"
fi
else
preFlight "Last position not found. Setting it to zero and continuing."
createLastErrorPosition
fi
}
preFlight "Creating Marker file and checking if last error position exists"
createMarkerFile
verifyLastPosition
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Complete
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
preFlight "Complete"
####################################################################################################
#
# Dialog Variables
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Dialog path and Command Files
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
dialogBinary="/usr/local/bin/dialog"
dialogCommandFile=$( mktemp /var/tmp/dialog.appAutoPatch.XXXXX )
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Reflect Debug Mode in `infotext` (i.e., bottom, left-hand corner of each dialog)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
case ${debugMode} in
"true" ) infoTextScriptVersion="DEBUG MODE | Dialog: v${dialogVersion} • ${scriptFunctionalName}: v${scriptVersion}" ;;
"verbose" ) infoTextScriptVersion="VERBOSE DEBUG MODE | Dialog: v${dialogVersion} • ${scripFunctionalName}: v${scriptVersion}" ;;
"false" ) infoTextScriptVersion="${scriptVersion}" ;;
esac
####################################################################################################
#
# List dialog
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# "list" dialog Title, Message, and Icon
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
dialogListConfigurationOptions=(
--title "${appTitle}"
--message "Updating the following apps …"
--commandfile "$dialogCommandFile"
--moveable
--button1text "Done"
--button1disabled
--height 600
--width 650
--position bottomright
--progress
--helpmessage "$helpMessage"
--infobox "**Computer Name:** \n\n- $computerName \n\n**macOS Version:** \n\n- $osVersion ($osBuild)"
--infotext "${infoTextScriptVersion}"
--windowbuttons min
--titlefont size=18
--messagefont size=14
--quitkey k
--icon "$icon"
--overlayicon "$overlayicon"
)
####################################################################################################
#
# Write dialog
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# "Write" dialog Title, Message and Icon
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
dialogWriteConfigurationOptions=(
--title "${appTitle}"
--message "Analyzing installed apps …"
--icon "$icon"
--overlayicon "$overlayicon"
--commandfile "$dialogCommandFile"
--moveable
--windowbuttons min
--mini
--position bottomright
--progress
--progresstext "Scanning …"
--quitkey k
)
####################################################################################################
#
# Functions
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Kill a specified process (thanks, @grahampugh!)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function killProcess() {
process="$1"
if process_pid=$( pgrep -a "${process}" 2>/dev/null ) ; then
infoOut "Attempting to terminate the '$process' process …"
infoOut "(Termination message indicates success.)"
kill "$process_pid" 2> /dev/null
if pgrep -a "$process" >/dev/null ; then
errorOut "'$process' could not be terminated."
fi
else
infoOut "The '$process' process isn't running."
fi
}
function check_and_echo_errors() {
# Create a timestamp for the current run
timestamp=$(date +%Y%m%d%H%M%S)
infoOut "Current time stamp: $timestamp"
# Create a directory for duplicate log files if it doesn't exist
if [ ! -d "$duplicate_log_dir" ]; then
mkdir -p "$duplicate_log_dir"
infoOut "Creating duplicate log file"
else
infoOut "Duplicate log directory exists, continuing"
fi
# Specify the duplicate log file with a timestamp
duplicate_installomatorLogFile="$duplicate_log_dir/Installomator_error_$timestamp.log"
infoOut "Duplicate Log File location: $duplicate_installomatorLogFile"
# Find the last position marker or start from the beginning if not found
if [ -f "$marker_file" ]; then
lastPosition=$(cat "$marker_file")
else
lastPosition=0
fi
# Copy new entries from Installomator.log to the duplicate log file
tail -n +$((lastPosition + 1)) "$installomatorLogFile" > "$duplicate_installomatorLogFile"
infoOut "tailing new entries from log file to duplicate log file"
# Update the marker file with the new position
wc -l "$installomatorLogFile" | awk '{print $1}' > "$marker_file"
infoOut "Updating marker file"
lastPosition=$(cat "$marker_file")
infoOut "Last position: $lastPosition"
result=$(grep -a 'ERROR\s\+:\s\+\S\+\s\+:\s\+ERROR:' "$duplicate_installomatorLogFile" | awk -F 'ERROR :' '{print $2}')
#infoOut "Install Error Result: $result"
#Function to print with bullet points
print_with_bullet() {
local input_text="$1"
while IFS= read -r line; do
echo "• $line"
echo # Add a space after each line
done <<< "$input_text"
}
# Print the formatted result with bullet points in the terminal
formatted_error_result=$(print_with_bullet "$result")
# Print the formatted result with bullet points in the infoOut message
infoOut "Install Error Result: $formatted_error_result"
}
function appsUpToDate(){
# Find the last position text in scriptLog
appsUpToDate=$(tail -n 200 "$scriptLog" | grep 'All apps are up to date. Nothing to do.' | tail -n 1)
errorsCount=$(echo $errorCount)
#Function to print with bullet points
print_with_bullet() {
local input_text="$1"
while IFS= read -r line; do
#echo "• $line"
echo # Add a space after each line
done <<< "$input_text"
}
if [ -n "$appsUpToDate" ]; then
formatted_app_result=$(echo "$appsUpToDate" | awk -F 'All apps are up to date. Nothing to do.' '{print $2}' | tr -d '[:space:]')
notice $formatted_app_result
else
notice "Apps were updated"
fi
# Extract the App up to date info from the AAP log
if [[ $errorsCount -le 0 ]] && [[ ! -n $appsUpToDate ]]; then
infoOut "SUCCESS: Applications updates were installed with no errors"
webhookStatus="Success: Apps updated (S/N ${serialNumber})"
formatted_result=$(echo "$queuedLabelsArray")
formatted_error_result="None"
errorCount="0"
elif
[[ $errorsCount -gt 0 ]] && [[ ! -n $appsUpToDate ]]; then
infoOut "FAILURES DETECTED: Applications updates were installed with some errors"
webhookStatus="Error: Update(s) failed (S/N ${serialNumber})"
formatted_result=$(echo "$queuedLabelsArray")
check_and_echo_errors
else
infoOut "SUCCESS: Applications were all up to date, nothing to install"
webhookStatus="Success: Apps already up-to-date (S/N ${serialNumber})"
formatted_result="None"
formatted_error_result="None"
errorCount="0"
fi
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Remove Installomator
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function removeInstallomator() {
if [[ "$removeInstallomatorPath" == "true" ]]; then
infoOut "Removing Installomator..."
rm -rf ${installomatorPath}
else
infoOut "Installomator removal set to false, continuing"
fi
}
removeInstallomatorOutDated() {
infoOut "Removing Installomator..."
rm -rf ${installomatorPath}
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Exit the caffeinated script
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function caffeinateExit() {
infoOut "De-caffeinate $aapPID..."
killProcess "caffeinate"
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Exit the Dialog
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function dialogExit() {
if [[ "$unattendedExit" == "true" ]]; then
infoOut "Unattended exit set to 'true', waiting $unattendedExitSeconds seconds then sending kill to Dialog"
sleep $unattendedExitSeconds
infoOut "Killing the dialog"
killProcess "Dialog"
else
infoOut "Unattended exit set to 'false', leaving dialog on screen"
fi
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Quit Script
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function rm_if_exists()
{
if [ -n "${1}" ] && [ -e "${1}" ];then
/bin/rm -r "${1}"
fi
}
function quitScript() {
quitOut "Exiting …"
# Stop `caffeinate` process
caffeinateExit
# Stop the `Dialog` process
dialogExit &
# Remove overlayicon
if [[ -e ${overlayicon} ]]; then
quitOut "Removing ${overlayicon} …"
rm "${overlayicon}"
fi
# Remove welcomeCommandFile
if [[ -e ${dialogCommandFile} ]]; then
quitOut "Removing ${dialogCommandFile} …"
rm "${dialogCommandFile}"
fi
# Remove duplicate log file
if [[ -d "${duplicate_log_dir}" ]]; then
quitOut "Removing "${duplicate_log_dir}" …"
rm_if_exists "${duplicate_log_dir}"
else
quitOut "Could not delete "${duplicate_log_dir}""
fi
# Remove Marker File
if [[ -e ${marker_file} ]]; then
quitOut "Removing ${marker_file} …"
rm "${marker_file}"
fi
exit $exitCode
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# swiftDialog Functions (thanks, @BigMacAdmin)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function swiftDialogCommand(){
if [ ${interactiveMode} -gt 0 ]; then
echo "$@" > "$dialogCommandFile"
sleep .2
fi
}
function swiftDialogListWindow(){
# If we are using SwiftDialog