Johnbritto
Johnbritto

Reputation: 149

how to stop tail -f command executed in sub shell

I tried various steps from http://mywiki.wooledge.org/ProcessManagement and http://mywiki.wooledge.org/BashFAQ/068My but I am unable to achieve is how to kill the tail -f command after certain time interval.

my script:

#!/bin/bash

function strt ()
{
command 1..
command 2..
}

export -f strt
su user -c 'set -e && RUN_Server.sh > server.log && tail -f server.log & pid=$! { sleep 20; kill $pid; } && strt'

exit 0.

I am trying to kill the pid of tail -f server.log and proceed to 'strt' which is small function to find if jboss server is started or not.

on executing I get error as

bash: -c: line 0: syntax error near unexpected token `{' .

Upvotes: 3

Views: 3507

Answers (4)

sdaau
sdaau

Reputation: 38649

I was trying something similar, namely wanted to print out the pid of a process spawned in the background with ampersand (&), in a one-liner/single line:

$ tail -f /var/log/syslog & ; echo $! 
bash: syntax error near unexpected token `;'

... but kept getting the dreaded syntax error, which brought me to this post.

What I failed to realize in my example above, is that the & (ampersand) is also a command separator/terminator in bash - just like the ; (semicolon) is!! Note:

BashSheet - Greg's Wiki

  • [command] ; [command] [newline]
    Semi-colons and newlines separate synchronous commands from each other.
  • [command] & [command]
    A single ampersand terminates an asynchronous command.

So - given that the &, which is a command line terminator in bash, in my example above is followed by a ;, which is also a command line terminator - bash chokes. The answer is simply to remove the semicolon ;, and let only the ampersand & act as a command line separator in the one-liner:

$ tail -f /var/log/syslog & echo $! 
[1] 15562
15562
$ May  1 05:39:16 mypc avahi-autoipd(eth0)[23315]: Got SIGTERM, quitting.
May  1 06:09:01 mypc CRON[2496]: (root) CMD (  [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -delete)
May  1 06:17:01 mypc CRON[5077]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)
May  1 06:25:01 mypc CRON[7587]: (root) CMD (test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ))
^C
$ May  1 06:52:01 mypc CRON[15934]: (root) CMD (test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly ))
$ ps -p 15562
  PID TTY          TIME CMD
15562 pts/0    00:00:00 tail
$ kill 15562
$ ps -p 15562
  PID TTY          TIME CMD
[1]+  Terminated              tail -f /var/log/syslog
$ ps -p 15562
  PID TTY          TIME CMD
$ 

... however, in this example, you have to manually kill the spawned process.

To go back to OP problem, I can reconstruct the problem with this command line:

$ tail -f /var/log/syslog & pid=$! { sleep 2; kill $pid; } 
bash: syntax error near unexpected token `}'

Thinking about this - bash sees & as separator, then sees "legal" command pid=$!, and then - with the previous "legal" command unterminated, sees a curly brace { which means a new command group in current shell. So the answer is simply to terminate the pid=$! with a semicolon ;, so the new command group can properly start:

$ tail -f /var/log/syslog & pid=$! ; { sleep 2; kill $pid; } 
[1] 20228
May  1 05:39:16 mypc avahi-autoipd(eth0)[23315]: Got SIGTERM, quitting.
May  1 06:09:01 mypc CRON[2496]: (root) CMD (  [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -delete)
May  1 06:17:01 mypc CRON[5077]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)
May  1 06:25:01 mypc CRON[7587]: (root) CMD (test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ))
May  1 06:52:01 mypc CRON[15934]: (root) CMD (test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly ))
$ ps -p 20228
  PID TTY          TIME CMD
[1]+  Terminated              tail -f /var/log/syslog
$ 

Note that the tail -f process seems to terminate property, but in my bash (version 4.2.8(1)), I have to press Enter in shell, to see the "[1]+ Terminated ..." message.

Hope this helps,
Cheers!

Upvotes: 0

Zombo
Zombo

Reputation: 1

Try this

timeout 20 tail -f server.log

Upvotes: 3

David W.
David W.

Reputation: 107040

The problem you're having is that you sleep command won't run until after you kill your tail.

The command structure:

command1 && command2

says to run command1 and if it exits with an exit code of 0, then run command2. It's equivalent to this:

if command1
then
     command2
fi

I had a similar situation to this a while ago. I had to start up a Weblogic server, wait until the server started, then do something on the server.

I ended up using named pipes (Directions) to do this. I ran the command that started the Weblogic server through this named pipe. I then had another process read the pipe, and when I saw the startup string, I broke out of my loop and continued my program.

The link above should give you complete directions on doing just that.

Upvotes: 0

choroba
choroba

Reputation: 241918

pid=$! { sleep 20 ; kill $pid; }

What are you trying to do? Maybe just adding a semicolon before { can help?

Upvotes: 0

Related Questions