简体   繁体   中英

Bash script hangs when called from php or python

I'm a novice at bash and I wrote a bash script that reads a large syslog file from end to start, looks for the entries that belong to a given minute (the minute before the last) and then counts how many ocurrences each of the given patterns has in that minute. It doesn't work if run from PHP/Python, but it works if I call it directly like this:

sh /path/to/logparser.sh /path/to/big.log '2013-09-23T08:38' '2013-09-23T08:37' 'MySQL has gone away' 'Unhandled Error timed out'

Below is the code of logparser.sh :

logfile=$1
echo $logfile
shift
minute=$1
echo $minute
shift
minute_before=$1
echo $minute_before
shift
command="tac $logfile | sed -n -e '/$minute/p' -e '/$minute_before/q'"
echo $command
if [ -f $logfile ]; then
    buffer=$(eval $command)
    echo "buffer complete"
    exit 1
fi

Side notes:

  • I've used buffer=$(eval $command) because buffer=$(tac $logfile | sed -n -e '/$minute/p' -e '/$minute_before/q') hangs even in the command line
  • I've used -e '/$minute_before/q' in sed because I couldn't get `-e '/$minute/!q' to work

But when I run it from PHP via pasthru() or from Python via subprocess.Popen().communicate() it hangs. If I check the processes with ps -ef r I see that tac is still running.

Here's the PHP code that calls the bash script:

$env           = $argv[1];
$service_name  = $argv[2];
$logfile       = $argv[3];
$minute        = $argv[4];
$minute_before = $argv[5];

$command = 'sh '.dirname(__FILE__).'/logparser.sh ';

$n = count($argv);
for($i=3; $i<$n; $i++){
    $command .= ' ' . escapeshellarg($argv[$i]);
}
$command .= "\n";
echo "\npassthru {$command}";
passthru($command, $out);
var_dump($out);
exit();

Here's the Python code that calls the bash script:

env           = sys.argv[1]
service_name  = sys.argv[2]
logfile       = sys.argv[3]
minute        = sys.argv[4]
minute_before = sys.argv[5]

args = ['sh', '%s/logparser.sh' % os.getcwd()]

for i in range(3, len(sys.argv)):
    args.append(sys.argv[i])

print args
output = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()
print output

Other stuff that I've rules out:

  • exec permissions: both PHP and Python can run and get the results of linux commands like whoami
  • file permissions: both PHP and Python run perfectly for a simpler bash script, eg a file containing the date liunx command; the log file has read permissions for all
  • bad params: I've compared in the bash script the params send by PHP/Python and the params sent via command line, they're identical

How could I make it work called from PHP/Python?

None of your codes seem to pass your logfile to your shell script, the logfile variable is unset in your shell making tac wait input from stdin instead.

Like in your python code, perhaps you need to do it like this:

for i in range(1, len(sys.argv)):
    args.append(sys.argv[i])

Likewise in your php code:

$n = count($argv);
for($i=1; $i<$n; $i++){
    $command .= ' ' . escapeshellarg($argv[$i]);
}

The actual cause why the logfile's path is not passed to your shell script may be different but generally that's the basic reason why the script is hanging.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM