2

I've a little problem, probably it's a stupid question, but I started learning bash about a week ago... I have 2 script, a.sh and b.sh. I need to make both running constantly. b.sh should waits for a signal from a.sh

(I'm trying to explain: a.sh and b.sh run --> a.sh sends a signal to b.sh -> b.sh traps signal, does something --> a.sh does something else and then sends another signal --> b.sh traps signal, does something --> etc.)

This is what I've tried:

a.sh:

#!/bin/bash
./b.sh &;
bpid=$!;
# do something.....
while true
do
     #do something....
     if [ condition ]
     then
          kill -SIGUSR1 $bpid;
     fi
done

b.sh:

#!/bin/bash 
while true
do
     trap "echo I'm here;" SIGUSR1;
done

When I run a.sh I get no output from b.sh, even if I redirect the standard output to a file... However, when I run b.sh in background from my bash shell, it seems to answer to my SIGUSR1 (sent with the same command, directly from shell) (I'm getting the right output) What I'm missing?

EDIT: this is a simple example that I'm trying to run:

a.sh:

#!/bin/bash
./b.sh &
lastpid=$!;
if [ "$1" == "something" ]
then    
    kill -SIGUSR1 $lastpid;
fi

b.sh:

#!/bin/bash
trap "echo testlog 1>temp" SIGUSR1;
while true
do
    wait
done

I can't get the file "temp" when running a.sh. However if I execute ./b.sh & and then kill -SIGUSR1 PIDOFB manually, everything working fine...

Milite
  • 23
  • 1
  • 1
  • 5
  • 2
    Also you don't need to install the trap repeatedly. Once is enough. And a while loop like that will absolutely **burn** through cpu. You should definitely add a short sleep in there. – Etan Reisner Sep 04 '14 at 15:07
  • thanks for your answers. Yeah, I know, just a writing error, in my test script I've got $lastpid, I miss to rename both here... Can b.sh run in background, without exiting, if it contain only trap without loop? And catch more than 1 signal? – Milite Sep 04 '14 at 15:45
  • 1
    Another typo I'm assuming is that `./b.sh &;` isn't valid. You can't have both `&` and `;` as terminators like that. When constructing a minimal test case you need to be careful to duplicate your actual case correctly. Have you tested this minimal case to see if it has the same problem as your real case? – Etan Reisner Sep 04 '14 at 15:49
  • 1
    I didn't say don't loop. I said don't set the trap in the loop. The trap doesn't go away when caught (as far as I know) so you only need to set the trap handler once. – Etan Reisner Sep 04 '14 at 15:50
  • You've also got a typo in the trap handler. That `\`` is unescaped and will cause a shell syntax error. – Etan Reisner Sep 04 '14 at 15:51
  • with &; I get error of course, my real case haven't it. And the echo command haven't any unescaped ` in real case, I'm sorry, I was late when I wrote this question... b.sh should contain only code for handling signal, how I can realize it without putting trap into the loop? I've tried to put trap out, but when b.sh is called, it run the while loop even if no signal has been delivered. And without a no-end while, script ends without waiting for signal... I'm missing some base info, I think – Milite Sep 04 '14 at 16:05
  • 1
    The loop just needs to keep your script from exiting. The trap handler does the work. The `trap "handler" SIGUSR1` command **adds** a trap handler it doesn't pause the script waiting for that signal to come in. Get a minimal *working* pair of scripts that fail and update your post with them. Until then this isn't solvable. – Etan Reisner Sep 04 '14 at 16:07
  • 1
    Those literal scripts work here. Though `a.sh` obviously only sends the signal to `b.sh` once then exits and leaves `b.sh` running. Also that `wait` isn't doing anything for you as `b.sh` has nothing to `wait` on and so `b.sh` still busy loops and eats up all your cpu. – Etan Reisner Sep 04 '14 at 16:25
  • You mean you can get temp file from `./a.sh something` run? I can't, tested on ubuntu and macos. I've tried to change permission, can't make this working... (I know there are many other problems in my script, but the main point is to make trap working..) – Milite Sep 04 '14 at 16:37
  • Yes. Those exact scripts create a temp file when run like that. (Though I will admit to having noticed a slight unreliability in this effect. Run it a few times and at least one will work. I expect that is a race between `b.sh` getting to the `trap` command and `a.sh` sending the signal. Adding a small sleep before the `if` seems to make it much more reliable.) – Etan Reisner Sep 04 '14 at 17:04

1 Answers1

2

One of the possible solutions would be the next one (perhaps, it's dirty one, but it works):

a.sh:

#!/bin/bash

BPIDFILE=b.pid

echo "a.sh: started"
echo "a.sh: starting b.sh.."

./b.sh &
sleep 1

BPID=`cat $BPIDFILE`

echo "a.sh: ok; b.sh pid: $BPID"

if [ "$1" == "something" ]; then
    kill -SIGUSR1 $BPID
fi

# cleaning up..
rm $BPIDFILE

echo "a.sh: quitting"

b.sh:

#!/bin/bash

BPIDFILE=b.pid

trap 'echo "got SIGUSR1" > b.log; echo "b.sh: quitting"; exit 0' SIGUSR1

echo "b.sh: started"

echo "b.sh: writing my PID to $BPIDFILE"
echo $$ > $BPIDFILE

while true; do
    sleep 3
done

The idea is to simply write down a PID value from within a b (background) script and read it from the a (main) script.

constt
  • 2,250
  • 1
  • 17
  • 18
  • 1
    working perfectly, thank you! I've just a little problem... why if I send a SIGINT from a.sh to b.sh, I can't trap it from b.sh while I can trap "CTRL+C" from a.sh? – Milite Sep 05 '14 at 11:04
  • No. SIGINT is useless for the background job. See the next link, it might be helpfull for you: http://stackoverflow.com/questions/14696427/how-can-bash-script-do-the-equivalent-of-ctrl-c-to-a-background-task – constt Sep 08 '14 at 02:08