3

I'm trying to write a batch script that creates new terminator terminals and then runs a process in each one. I want them to keep running in the background until I decide to kill them.

I want the first one to run for 10 seconds and then afterwards create a bunch of other terminator processes simultaneously.

This first part far works but now I want to, at the end, be able to press enter and send a SIGINT to every process that I started. I can't figure out a command that works for this purpose.

#!/bin/sh
echo "Running Teleop... (MAY TAKE SEVERAL SECONDS TO INITIALIZE)"

terminator -T "gazebo" -e "roslaunch cob_bringup_sim robot.launch 
robot:=cob4-8 robot_env:=ipa-apartment; bash" &

#wait 10 secons before starting nav and rviz otherwise will get error
((sleep 10) &&
(terminator -T "navigation" -e "roslaunch cob_navigation_global 
2dnav_ros_dwa.launch robot:=cob4-5 robot_env:=ipa-apartment; bash" &
terminator -T "rviz" -e "roslaunch cob_navigation_global rviz.launch; 
bash" &
terminator -T "arm_controller" -e "roslaunch cob_moveit_bringup 
demo.launch rviz_tutorial:=true robot:=cob4-8; bash" &
terminator -T "control_nodes" -e "cd catkin_ws; rosrun first_pkg 
control_nodes; bash" &
terminator -T "controller" -e "cd catkin_ws; rosrun first_pkg 
controller; bash" &
terminator -T "joystick" -e "rosrun joy joy_node; bash" &
#spawn objects
terminator -T "spawn_objects_launch" -e "roslaunch 
cob_default_env_config upload_object_locations.launch robot_env:=ipa- 
apartment; rosrun cob_bringup_sim spawn_object.py tomato_sauce; 
bash")) &

(
echo Press any key to to shutdown all processes
read varname
echo Shutting down...
#terminating all child processes
)

These are ROS commands but I assume there is no difference between them and generic commands in this case. I realize the code is quite messy and if there are any other issues you see with it I'd be glad to hear it. Thanks!

1 Answers1

2

When run non-interactively (e.g. in a script), bash disables job control, so easy methods of killing background processes, such as those in Kill all background jobs or How to kill all jobs in bash? won't work by default.

The first thing I would do is to ensure that you're running bash by changing the sh-bang line to:

#!/bin/bash

Next, let's enable job control (aka "monitor mode") so that we can use one of the easy solutions from those previous questions:

set -m

Next, I would simplify most of your subshell activity; you don't need them. With simplified commands, just to demonstrate the point:

#wait 10 seconds before starting nav and rviz otherwise will get error
sleep 10 || exit
terminator -T "navigation ... bash" &
terminator -T "rviz ... bash" &
...
terminator -T "spawn_objects_launch" &

echo Press any key to to shutdown all processes
read varname
echo Shutting down...

You don't have to start an entire subshell (and background it) for all of the terminator processes. You don't need to run the sleep 10 in a subshell. You don't really need to test the return code of sleep 10 in order to chain the subsequent commands, with &&. I've adapted the code to match the existing behavior: if the sleep command fails (say, you hit Control-C), then the script will exit and not start the subsequent terminator processes.

Lastly, add the code to kill off the child processes:

...
terminator -T "spawn_objects_launch" &

echo Press ENTER to shutdown all processes
read 
echo Shutting down...
kill $(jobs -p)

I rephrased the prompt; you'd need to enter (almost) any key and then press ENTER in order for the read command to see your input, so I simply suggest that the user press ENTER. Next, the read command accepts a variable name, but there's a default variable named REPLY that it will use if you don't specify your own variable name, so depending on whether that's more obvious to you, that's another option to simplify the code.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255