2

我有一个 php 脚本,它通过传递参数来运行另一个期望脚本。

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

使用 shell_exec 不起作用,因为脚本在后台运行或在 php 脚本中运行。我需要它在前台运行,允许用户交互。有没有一种优雅的方式来做到这一点。由于不得不使用不同的脚本语言,它已经变得一团糟。我尝试用一​​个调用 php 脚本的 shell 脚本来包装这两个脚本,将结果分配为一个变量(这是一个命令),然后在其上运行 sh。但是,当脚本在后台运行并且任何用户交互都会导致暂停/冻结时,我又遇到了同样的问题。如果 php 在调用 shell exec 时“退出”,在这种情况下就可以了。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 脚本,例如my-script 'param1' 'param2' 并且可以被认为是完全“异步”的。这很像“launchy”或“synapse”等启动程序的行为,它们可以启动其他程序但不需要影响它们。他们也不会等待辅助程序退出/完成。

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

4

4 回答 4

1

最后,我设法通过添加第三个引号类型来使其工作:`(我相信它被称为“大头钉”?)它允许我将参数从第一个脚本传递给下一个脚本

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

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

需要一段时间才能正确引用所有引号,因为交换引号类型可能会导致它无法正常工作。

这是一个演示最终结果的视频

于 2013-01-27T02:11:36.167 回答
1

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

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

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

在此处输入图像描述

如果你同时有很多用户并且用户和进程之间通信很多,你可以在内存中挂载一个分区来优化读/写操作。

在您的 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 个进程)
  • ...
于 2013-01-24T22:34:08.777 回答
1

我认为您正在寻找的是proc_open()命令。它使您可以访问后台进程的标准输入/标准输出流。您可以在$descriptorSpec参数中将自己的 stdin/stdout 流传递给新进程,这将使您的后台进程与用户对话。

您的“前台”应用程序将不得不等待,直到后台进程终止。我实际上并没有用 PHP 做到这一点,但我猜你必须观察$pipes才能看到它们何时关闭——然后你就会知道后台进程已经完成,你可以删除进程资源和继续执行前台进程需要做的任何事情。

于 2013-01-24T22:49:37.440 回答
1

利用:

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']
));
于 2013-02-01T18:01:21.337 回答