从php或python调用时,Bash脚本会挂起

时间:2013-09-23 10:00:13

标签: php python linux bash sed

我是bash的新手,我写了一个bash脚本,从头到尾读取一个大的syslog文件,查找属于给定分钟(最后一分钟)的条目然后计算多少每一个给定模式的发生在那一分钟。 如果从PHP / Python运行它不起作用,但是如果我直接调用它就可以工作:

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'

以下是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

附注:

  • 我已使用buffer=$(eval $command),因为buffer=$(tac $logfile | sed -n -e '/$minute/p' -e '/$minute_before/q')甚至在命令行中挂起
  • 我在sed中使用了-e '/$minute_before/q',因为我无法获得`-e' / $ minute /!q'工作

但是当我通过pasthru()从PHP运行它或通过subprocess.Popen().communicate()从Python运行它时它会挂起。如果我使用ps -ef r检查流程,我发现tac仍在运行。

这是调用bash脚本的PHP代码:

$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();

这是调用bash脚本的Python代码:

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

我排除的其他内容:

  • exec权限:PHP和Python都可以运行并获取linux命令的结果,如whoami
  • 文件权限:PHP和Python都可以完美地运行一个更简单的bash脚本,例如:包含date liunx命令的文件;日志文件具有所有
  • 的读取权限
  • 糟糕的参数:我在bash脚本中比较了PHP / Python发送的params和通过命令行发送的params,它们是相同的

如何让它从PHP / Python调用?

1 个答案:

答案 0 :(得分:2)

你的代码似乎都没有将你的日志文件传递给你的shell脚本,你的shell中没有设置logfile变量,而是从stdin中输入tac wait输入。

就像你的python代码一样,也许你需要这样做:

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

同样在你的PHP代码中:

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

日志文件路径未传递给shell脚本的实际原因可能不同,但通常是脚本挂起的基本原因。