php在前台运行另一个脚本

时间:2013-01-24 19:09:08

标签: php bash exec expect

我有一个php脚本,可以通过传递参数来运行另一个expect脚本。

$output = shell_exec("expect login_script.tcl '$user' '$host' '$port' '$password'");

使用shell_exec不起作用,因为脚本在后台运行或在php脚本中运行。我需要它在前台运行,允许用户交互。是否有一种优雅的方式来做到这一点。必须使用不同的脚本语言已经变得混乱了。我尝试用一​​个调用php脚本的shell脚本包装这两个脚本,将结果作为变量分配输出(这是一个命令)然后运行它。但是我再次遇到相同的问题,脚本在后台运行,任何用户交互都会产生暂停/冻结。如果在调用shell exec时php'退出',这种情况就可以了。 IE浏览器。 php停止并期望像你调用它一样运行。 (就像我刚刚复制输出的命令并将其粘贴到终端中一样)。


更新 我在php中使用以下命令运气得多:

shell_exec("gnome-terminal -e 'bash -c \"expect ~/commands/login_script.tcl; exec bash\"' &");

但是,为了在辅助脚本(login_script)完成后不立即关闭shell,可以改进吗?


进一步更新

通过阅读答案,我认为我需要澄清事情,因为看起来人们正在承担一个“更复杂”的问题。

  • 这两个进程不需要相互通信,我可能不会将$output = shell_exec放在示例中而只是shell_exec自己,因为我相信这导致了混乱。

  • php脚本只需启动带有一些cli参数的expect脚本,例如:我的脚本'param1''param2'可以被认为是完全'异步'。这很像启动程序的行为,如'launchy'或'synapse',它们可以启动其他程序但不需要影响它们。他们也不会等待二级计划退出/结束。

  • 我错误地说'shell_exec'对我不起作用。我应该说的是'我到目前为止还没有成功使用shell_exec',但是shell_exec("gnome-terminal -e 'bash -c \"expect ~/commands/login_script.tcl; exec bash\"' &");是'工作'但仍然试图找到正确的引用组合以允许将参数传递给expect脚本。

4 个答案:

答案 0 :(得分:0)

任务管理是一项有趣但困难的工作。

因为您的用户可以在任务期间移动(并导致意外结果,例如会话冻结,或者流程中的工作不完整),您需要在后台执行它。如果您需要在用户和流程之间进行交互,则需要创建一种沟通方式。

最简单的方法(我认为)是使用在用户会话和任务之间共享的文件。

enter image description here

如果您同时拥有大量用户并在用户和进程之间进行大量通信,则可以在内存中安装分区以优化读/写操作。

在你的fstab中,有一行:

tmpfs /memory       tmpfs defaults,uid=www-data,gid=www-data,size=128M 0 0

或者,在脚本中,您可以这样做:

#!/bin/sh
mkfs -t ext2 -q /dev/ram1 65536
[ ! -d /memory ] && mkdir -p /memory
mount /dev/ram1 /memory
chmod -R 777 /memory

你需要处理很多事情:

  • 文件访问(以避免webapp与流程之间的并发)
  • 时间(避免僵尸或无用的长时间运行的脚本)
  • 安全性(必须仔细设计此类操作)
  • 资源管理(以避免10000个进程同时运行)
  • ...

答案 1 :(得分:0)

我认为您正在寻找的是proc_open()命令。它使您可以访问后台进程的stdin / stdout流。您可以将自己的stdin / stdout流传递到 $ descriptorSpec 参数中的新进程,这将让您的后台进程与用户通信。

你的'前景'应用程序必须等待,直到后台进程死亡。我还没有用PHP完成这个,但我猜你必须看 $ pipes 来看看它们什么时候关闭 - 那么你就会知道后台进程已经完成了您可以删除进程资源并继续处理前台进程需要执行的任何操作。

答案 2 :(得分:0)

最后,我设法通过添加第三个引号类型来实现它:`(我相信它被称为'tack'?),它允许我将参数传递给第一个脚本中的下一个脚本< / p>

我在php脚本中需要的命令是:

$command = `gnome-terminal -e 'bash -c "expect ~/commands/login_script.tcl \"$user\" \"$host\" \"$port\" \"$password\"; exec bash"' &`;
shell_exec($command);

需要一段时间才能获得所有报价,因为交换报价类型会导致报价无法正常工作。

这是video demonstrating the end result

答案 3 :(得分:0)

使用:

pcntl_exec("command", array("parameter1", "parameter2"));

例如,我有一个脚本,它使用当前php项目中的参数启动mysql命令,如下所示:

pcntl_exec("/usr/bin/mysql", array(
    "--user=".$params['user'],
    "--password=".$params['password'],
    "--host=".$params['host'],
    $params['dbname']
));

这不依赖于gnome终端或任何东西,它将PHP替换为您调用的程序。

您确实需要知道命令的完整路径,这很痛苦,因为它可能因平台而异,但您可以使用env命令命令,该命令在大多数系统上/usr/bin/env处可用为你找到命令。上面的例子变成了:

pcntl_exec("/usr/bin/env", array(
    "mysql",
    "--user=".$params['user'],
    "--password=".$params['password'],
    "--host=".$params['host'],
    $params['dbname']
));