19

I have a previously running process (process1.sh) that is running in the background with a PID of 1111 (or some other arbitrary number). How could I send something like command option1 option2 to that process with a PID of 1111?

I don't want to start a new process1.sh!

codeforester
  • 39,467
  • 16
  • 112
  • 140
Mohit Deshpande
  • 53,877
  • 76
  • 193
  • 251

6 Answers6

15

Named Pipes are your friend. See the article Linux Journal: Using Named Pipes (FIFOs) with Bash.

kba
  • 19,333
  • 5
  • 62
  • 89
haknick
  • 1,892
  • 1
  • 20
  • 28
  • 1
    The article is great, but a how could I send the "something somethingelse yetanotherthing" to the process? For example, I have a server running that accepts, "something" and does something with it. How could I do this? – Mohit Deshpande May 13 '11 at 22:22
8

Based on the answers:

  1. Writing to stdin of background process
  2. Accessing bash command line args $@ vs $*
  3. Why my named pipe input command line just hangs when it is called?
  4. Can I redirect output to a log file and background a process at the same time?

I wrote two shell scripts to communicate with my game server.


This first script is run when computer start up. It does start the server and configure it to read/receive my commands while it run in background:

start_czero_server.sh

#!/bin/sh

# Go to the game server application folder where the game application `hlds_run` is
cd /home/user/Half-Life

# Set up a pipe named `/tmp/srv-input`
rm /tmp/srv-input
mkfifo /tmp/srv-input

# To avoid your server to receive a EOF. At least one process must have
# the fifo opened in writing so your server does not receive a EOF.
cat > /tmp/srv-input &

# The PID of this command is saved in the /tmp/srv-input-cat-pid file
# for latter kill.
# 
# To send a EOF to your server, you need to kill the `cat > /tmp/srv-input` process
# which PID has been saved in the `/tmp/srv-input-cat-pid file`.
echo $! > /tmp/srv-input-cat-pid

# Start the server reading from the pipe named `/tmp/srv-input`
# And also output all its console to the file `/home/user/Half-Life/my_logs.txt`
#
# Replace the `./hlds_run -console -game czero +port 27015` by your application command
./hlds_run -console -game czero +port 27015 > my_logs.txt 2>&1 < /tmp/srv-input &

# Successful execution 
exit 0

This second script it just a wrapper which allow me easily to send commands to the my server:

send.sh

half_life_folder="/home/jack/Steam/steamapps/common/Half-Life"

half_life_pid_tail_file_name=hlds_logs_tail_pid.txt
half_life_pid_tail="$(cat $half_life_folder/$half_life_pid_tail_file_name)"

if ps -p $half_life_pid_tail > /dev/null
then
    echo "$half_life_pid_tail is running"
else   
    echo "Starting the tailing..."
    tail -2f $half_life_folder/my_logs.txt &
    echo $! > $half_life_folder/$half_life_pid_tail_file_name
fi

echo "$@" > /tmp/srv-input
sleep 1

exit 0

Now every time I want to send a command to my server I just do on the terminal:

./send.sh mp_timelimit 30

This script allows me to keep tailing the process on your current terminal, because every time I send a command, it checks whether there is a tail process running in background. If not, it just start one and every time the process sends outputs, I can see it on the terminal I used to send the command, just like for the applications you run appending the & operator.


You could always keep another open terminal open just to listen to my server server console. To do it just use the tail command with the -f flag to follow my server console output:

./tail -f /home/user/Half-Life/my_logs.txt
Evandro Coan
  • 8,560
  • 11
  • 83
  • 144
2

If you don't want to be limited to signals, your program must support one of the Inter Process Communication methods. See the corresponding Wikipedia article.

A simple method is to make it listen for commands on a Unix domain socket.

Andre Holzner
  • 18,333
  • 6
  • 54
  • 63
2

For how to send commands to a server via a named pipe (fifo) from the shell see here:

Redirecting input of application (java) but still allowing stdin in BASH

How do I use exec 3>myfifo in a script, and not have echo foo>&3 close the pipe?

Community
  • 1
  • 1
maniq
  • 21
  • 1
2

You can use the bash's coproc comamnd. (avaliable only in 4.0+) - it's like ksh's |&

check this for examples http://wiki.bash-hackers.org/syntax/keywords/coproc

clt60
  • 62,119
  • 17
  • 107
  • 194
1

you can't send new args to a running process.

But if you are implementing this process or its a process that can take the args from a pipe, then the other answer would help.

nhed
  • 5,774
  • 3
  • 30
  • 44
  • Wrong, you can use a named pipe for this sort of thing. – mu is too short May 13 '11 at 22:03
  • @mu to me the question reads like the user wants to get new args (argc/argv in C or positional params in bash). Once the program starts you cannot give it new args. Pipes may solve his problem if he was the author of the app. He could also implement a TCP server ... but if you are talking about an existing command - then no (if he would have said, I am writing this app that I want to run in the bg ....) – nhed May 13 '11 at 22:08
  • There is some ambiguity in the question but I didn't read "send something like 'command option1 option2'" to mean modifying `argv` after the fact, looks to me that Mohit just wants to send a message of some sort to a backgrounded shell script. – mu is too short May 13 '11 at 22:33