0

I have a bash script set up to monitor a number of UDP streams and convert it into actionable data. My problem is that I need to set the script to periodically check to see if the stream capture is running and restart it if it isn't.

The challenge is to create a new process name or ID for each stream capture and check to see if it's running.

Here's a watered down version of what I've got. I'm hoping someone can tell me if I'm on the right track or not:

Subscriber () { processName="$1$2$4"; echo "$processName"; pgrep $processName; if [[ $? -ne 0 ]] ; then echo "Subcription for $1 with IP $2 not found, restarting." ; while read -re -t 43200 doc; do <Code to analyze stream> done < <(bash -c "exec -a $processName <Commands to capture stream as JSON doc>") else echo "Subcription for $1 wtih IP $2 found to be running, skipping." ; fi } while read line; do Subscriber $line; done < $flatFile 

Ideally, I'd like to get a process ID or name for the entire string of commands listed after exec -a, but it currently only taking the first command, which seems to be sort of working, but I'm not confident it will do what I'm wanting it to do.

The flatFile reference is a dynamically updated flatfile listing several hundred streams I'm monitoring.

2
  • Might using systemd to launch and restart the stream processors be a better solution? Commented Jul 21, 2023 at 7:27
  • So many questions....why exec? Why implementing the process management in the script? What "entire string of commands" - only 2 shown here and the "bash -c" appears redundant. Is $processName expected to be unique? Is one instance of $processName handling a single stream or all the streams? No, I suspect you're not on the right path but there's not enough information here to be sure / recommend a better approach. But you might start by looking at systemd or djbdaemontools for your process management. Commented Jul 21, 2023 at 8:25

1 Answer 1

0

The name of a process on Linux at least is changed every time the process executes a command, but is changed to the basename of the file that is executed, not to the argv[0] that bash allows passing with exec -a.

pgrep can match on the arg list (joined with spaces) with the -f option though, but note that like for grep, pgrep does regular expression matching, so you'd need to construct a regexp to match the argv[0] you want.

Or you could make sure the name you pass to exec -a doesn't contain regexp characters (including . common in IPv4 addresses).

Subscriber () { process_arg0="$1$2$4" # change all regex operators and space to _ process_arg0="${process_arg0//[][ .\\+?\$^()*{\}]/_}" printf>&2 '%s\n' "$process_arg0" if ! LC_ALL=C pgrep -f "^$process_arg0( |\$)"; then printf>&2 '%s\n' "Subscription for $1 with IP $2 not found, restarting." while IFS= read -r -t 43200 doc; do <Code to analyze stream> done < <( exec -a "$process_arg0" <Commands to capture stream as JSON doc> ) else printf>&2 '%s\n' "Subscription for $1 with IP $2 found to be running, skipping." fi } 

(also removing some other obvious errors like unquoted quotes, usage of echo, nonsensical -e option for read, missing IFS= for read, variable data embedded in interpreter code).

In any case, matching processes by name or arg list is very brittle and dangerous as any process can assign themselves any name or arg list they want, and the approach used here introduces race conditions. Using proper process overseers / supervisors such as your init system (systemd, upstart and co) or dedicated tools such as runit, daemontools, supervisor, start-stop-daemon would likely be more appropriate.

1
  • Thanks! I see why it was sort of working now. Definitely worth taking a look at some other approaches. I appreciate the sanity check! Commented Jul 21, 2023 at 15:34

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.