eventlisten.sh 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #!/bin/sh
  2. #
  3. # The following example monitors Salt's event bus in a background process
  4. # watching for returns for a given job. Requires a POSIX environment and jq
  5. # <http://stedolan.github.io/jq/>.
  6. #
  7. # Usage: ./eventlisten.sh '*' test.sleep 10
  8. # Mimic fnmatch from the Python stdlib.
  9. fnmatch() { case "$2" in $1) return 0 ;; *) return 1 ;; esac ; }
  10. count() { printf '%s\n' "$#" ; }
  11. listen() {
  12. events='events'
  13. mkfifo $events
  14. exec 3<>$events # Hold the fd open.
  15. # Start listening to events before starting the command to avoid race
  16. # conditions.
  17. salt-run state.event count=-1 >&3 &
  18. events_pid=$!
  19. (
  20. timeout=$(( 60 * 60 ))
  21. sleep $timeout
  22. kill -s USR2 $$
  23. ) &
  24. timeout_pid=$!
  25. # Give the runner a few to connect to the event bus.
  26. printf 'Subscribing to the Salt event bus...\n'
  27. sleep 4
  28. trap '
  29. excode=$?; trap - EXIT;
  30. exec 3>&-
  31. kill '"${timeout_pid}"'
  32. kill '"${events_pid}"'
  33. rm '"${events}"'
  34. exit
  35. echo $excode
  36. ' INT TERM EXIT
  37. trap '
  38. printf '\''Timeout reached; exiting.\n'\''
  39. exit 4
  40. ' USR2
  41. # Run the command and get the JID.
  42. jid=$(salt --async "$@")
  43. jid="${jid#*: }" # Remove leading text up to the colon.
  44. # Create the event tags to listen for.
  45. start_tag="salt/job/${jid}/new"
  46. ret_tag="salt/job/${jid}/ret/*"
  47. # ``read`` will block when no events are going through the bus.
  48. printf 'Waiting for tag %s\n' "$ret_tag"
  49. while read -r tag data; do
  50. if fnmatch "$start_tag" "$tag"; then
  51. minions=$(printf '%s\n' "${data}" | jq -r '.["minions"][]')
  52. num_minions=$(count $minions)
  53. printf 'Waiting for %s minions.\n' "$num_minions"
  54. continue
  55. fi
  56. if fnmatch "$ret_tag" "$tag"; then
  57. mid="${tag##*/}"
  58. printf 'Got return for %s.\n' "$mid"
  59. printf 'Pretty-printing event: %s\n' "$tag"
  60. printf '%s\n' "$data" | jq .
  61. minions="$(printf '%s\n' "$minions" | sed -e '/'"$mid"'/d')"
  62. num_minions=$(count $minions)
  63. if [ $((num_minions)) -eq 0 ]; then
  64. printf 'All minions returned.\n'
  65. break
  66. else
  67. printf 'Remaining minions: %s\n' "$num_minions"
  68. fi
  69. else
  70. printf 'Skipping tag: %s\n' "$tag"
  71. continue
  72. fi
  73. done <&3
  74. }
  75. listen "$@"