3

This is the script that I am using for running the command in background and counting the time needed for action after specified period elapses. There are also traps that will kill long running command started in background if I kill the main script earlier than I've planed.

#!/bin/bash
# DESCRIPTION:
# Run long running command in background for number of seconds
# specified in $TIME_TO_RUN. After this period the function
# 'func_action' will be called

func_trap () {
  # FOLLOWING LINE ADDED ACORDING TO Barmar SUGGESTION:
  # http://stackoverflow.com/questions/30112607/taking-action-after-timeout-during-the-command-running
  for pid in $(jobs -p); do ps -p $pid; done

  CHILDREN=$(jobs -p)
  if [ -n "$CHILDREN" ]; then
    echo "Following children will be killed"
    jobs -p
    kill $(jobs -p)
  else
    echo "There are no children running"
  fi
  exit
}

func_action() {
    echo "FUNCTION ACTION CALLED"
}
###################################
trap func_trap INT TERM KILL

LOG_PATH="/tmp/log_file"
TIME_TO_RUN=10
TIME_START=$(date +%s)
TIME_STOP=$(( TIME_START + TIME_TO_RUN ))

# COMMAND RUNNING IN BACKGROUND FOR INFINITE
while true;       do date;    sleep 1; done > "$LOG_PATH" &

# COMMAND RUNNING IN BACKGROUND FOR LONG TIME
# for i in `seq 1 5`; do echo $i; sleep 1; done > "$LOG_PATH" &

BKGRD_CMD_PID=$!

echo "BKGRD_CMD_PID: $BKGRD_CMD_PID"
echo "PID: $BKGRD_CMD_PID IS WRITING TO: $LOG_PATH"
echo "MYPID:         $$"
echo "TIME_START:    $TIME_START"
echo "TIME_STOP:     $TIME_STOP"
echo "jobs -p:       $(jobs -p)"

# TODO: TRY TO USE SLEEP INSTEAD OF LOOP
while true; do
  if [ $(date +%s) -lt $TIME_STOP ]; then
    echo -n "Long running command is still running at time: "
    date +%s
    sleep 1
  else
    kill -s 0 "$BKGRD_CMD_PID" 2>/dev/null && func_action
    kill -s 0 "$BKGRD_CMD_PID" 2>/dev/null && kill "$BKGRD_CMD_PID" && echo "Process with PID: $BKGRD_CMD_PID killed"
    break
  fi
done

When I kill this script using ctrl+c I get following message:

└──> time_counter.sh
BKGRD_CMD_PID: 7551
PID: 7551 IS WRITING TO: /tmp/log_file
MYPID:         7549
TIME_START:    1431161303
TIME_STOP:     1431161313
jobs -p:       7551
Long running command is still running at time: 1431161303
Long running command is still running at time: 1431161304
Long running command is still running at time: 1431161305
Long running command is still running at time: 1431161306
^C  PID TTY          TIME CMD
 7551 pts/4    00:00:00 time_counter.sh
  PID TTY          TIME CMD
Following children will be killed
7551
7572
7578
7579
/home/wakatana/bin/time_counter.sh: line 16: kill: (7572) - No such process
/home/wakatana/bin/time_counter.sh: line 16: kill: (7578) - No such process
/home/wakatana/bin/time_counter.sh: line 16: kill: (7579) - No such process

In general it works as expected I just want to clarify three things:

  1. Why I get error regarding PIDs 7572, 7578, 7579? Which process does those PIDs belongs to?
  2. Is this approach OK or there is better way to do it?
  3. How can I move func_trap and func_action to the end of script without bash complaining about unknown command?

PS: First time I was thinking about timeout command but seems like it can only send kill signals after specifed time period and don't do any other actions.

Wakan Tanka
  • 7,542
  • 16
  • 69
  • 122

1 Answers1

1

I suspect this a bash bug. While the trap handler is running, it seems to consider the sleep 1 that it interrupted from the main loop (the one that keeps printing "Long running command") to be a pending job.

Instead of kill $(jobs -p), you should do kill $BKGRD_CMD_PID.

Barmar
  • 741,623
  • 53
  • 500
  • 612