Skip to main content
Solved

Bash Script Self Service results

  • March 19, 2026
  • 4 replies
  • 22 views

Wanderers7
Forum|alt.badge.img+1

Hi, I am running a  vendor bash script from self service as part of a remediation effort. As part of the script there is a device shutdown. This happens before the device feeds back policy logs so if it fails I cant see why.

 

Would anyone know if sh scripts and their results get logged automatically somewhere or if there is a simple command to get them to do so?

 

Alternatively presumably I could remove the reboot from the script and have the JAMF policy do that?

Best answer by Chubs

Yep so the best thing to do here is to have the policy call the reboot. That way the policy controls when it happens and can gracefully exit. 
 

if you need additional logging, build that into the script and house the transcript somewhere on the machine for later troubleshooting. 

4 replies

Chubs
Forum|alt.badge.img+24
  • Jamf Heroes
  • Answer
  • March 19, 2026

Yep so the best thing to do here is to have the policy call the reboot. That way the policy controls when it happens and can gracefully exit. 
 

if you need additional logging, build that into the script and house the transcript somewhere on the machine for later troubleshooting. 


Wanderers7
Forum|alt.badge.img+1
  • Author
  • New Contributor
  • March 19, 2026

Thanks, Can see the error now properly in the policy log.


FerrisBNA
Forum|alt.badge.img+3
  • Contributor
  • March 19, 2026

Copilot helped me out with this one, so might need some touch ups. 

My thought is for the Self Service item to to run this script below.  And the Vendor script you want will be set to run as a custom trigger.

The Self Service script triggers your vendor script, checks if it is still running, runs an inventory update, then triggers a shutdown.

A log file for this is generated on the local device for troubleshooting.

I hope this helps.

-Pat

#!/bin/bash
# Replace all < > entries with your stuff

set -euo pipefail

JAMF_BIN="/usr/local/bin/jamf"
TRIGGER="<POLICY TRIGGER>"
LOG="/var/log/<NAME HERE>.log"

log() { printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" | tee -a "$LOG"; }

require_jamf() {
if [ ! -x "$JAMF_BIN" ]; then
log "ERROR: Jamf binary not found at $JAMF_BIN"
exit 1
fi
}

wait_for_jamf() {
# Wait until jamf binary not active
local timeout=300
local waited=0
while pgrep -q -f "/usr/local/bin/jamf"; do
sleep 2
waited=$((waited+2))
if [ $waited -ge $timeout ]; then
log "WARN: Jamf processes still running after $timeout s; continuing"
break
fi
done
}

run_policy() {
log "Running custom trigger: $TRIGGER"
if ! "$JAMF_BIN" policy -event "$TRIGGER" >>"$LOG" 2>&1; then
log "ERROR: jamf policy -event $TRIGGER failed"
# Continue; we still want to update inventory and shut down
fi
}

post_inventory() {
# Best-effort inventory update to push latest logs/inventory
log "Posting inventory (recon)"
if ! "$JAMF_BIN" recon >>"$LOG" 2>&1; then
log "WARN: jamf recon failed; will retry once after 10s"
sleep 10
"$JAMF_BIN" recon >>"$LOG" 2>&1 || log "WARN: jamf recon second attempt failed"
fi
}

shutdown_machine() {
log "Initiating shutdown in 30 seconds"
/sbin/shutdown -h +0.5 "System will shut down momentarily for maintenance." >/dev/null 2>&1 || \
/sbin/shutdown -h now
}

main() {
require_jamf
wait_for_jamf
run_policy
wait_for_jamf
post_inventory
wait_for_jamf
shutdown_machine
}

main
exit 0

 


Wanderers7
Forum|alt.badge.img+1
  • Author
  • New Contributor
  • March 19, 2026

Copilot helped me out with this one, so might need some touch ups. 

My thought is for the Self Service item to to run this script below.  And the Vendor script you want will be set to run as a custom trigger.

The Self Service script triggers your vendor script, checks if it is still running, runs an inventory update, then triggers a shutdown.

A log file for this is generated on the local device for troubleshooting.

I hope this helps.

-Pat

#!/bin/bash
# Replace all < > entries with your stuff

set -euo pipefail

JAMF_BIN="/usr/local/bin/jamf"
TRIGGER="<POLICY TRIGGER>"
LOG="/var/log/<NAME HERE>.log"

log() { printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" | tee -a "$LOG"; }

require_jamf() {
if [ ! -x "$JAMF_BIN" ]; then
log "ERROR: Jamf binary not found at $JAMF_BIN"
exit 1
fi
}

wait_for_jamf() {
# Wait until jamf binary not active
local timeout=300
local waited=0
while pgrep -q -f "/usr/local/bin/jamf"; do
sleep 2
waited=$((waited+2))
if [ $waited -ge $timeout ]; then
log "WARN: Jamf processes still running after $timeout s; continuing"
break
fi
done
}

run_policy() {
log "Running custom trigger: $TRIGGER"
if ! "$JAMF_BIN" policy -event "$TRIGGER" >>"$LOG" 2>&1; then
log "ERROR: jamf policy -event $TRIGGER failed"
# Continue; we still want to update inventory and shut down
fi
}

post_inventory() {
# Best-effort inventory update to push latest logs/inventory
log "Posting inventory (recon)"
if ! "$JAMF_BIN" recon >>"$LOG" 2>&1; then
log "WARN: jamf recon failed; will retry once after 10s"
sleep 10
"$JAMF_BIN" recon >>"$LOG" 2>&1 || log "WARN: jamf recon second attempt failed"
fi
}

shutdown_machine() {
log "Initiating shutdown in 30 seconds"
/sbin/shutdown -h +0.5 "System will shut down momentarily for maintenance." >/dev/null 2>&1 || \
/sbin/shutdown -h now
}

main() {
require_jamf
wait_for_jamf
run_policy
wait_for_jamf
post_inventory
wait_for_jamf
shutdown_machine
}

main
exit 0

 

Cool, but probably overkill for this use case, no doubt will help others so thanks.