当我调用脚本并让脚本保持运行时,C ++应用程序会在退出时挂起

时间:2014-04-03 17:43:06

标签: c++ linux bash qt shell

我在Ubuntu 10.04上运行了一个C ++ / Qt程序。我使用带有RSA密钥的x-windows(ssh -X)运行远程应用程序以防止密码对话。 C ++ / Qt程序允许用户调用shell脚本。 C ++ / Qt程序必须以' gksudo -k'。

运行

我遇到的问题是,当我从程序中调用shell脚本时,如果我让远程应用程序保持运行,它会导致本地C ++ / Qt程序中的线程挂起。 (我希望能够让ssh会话继续运行,而不会影响重启C ++ / Qt程序)

从C ++代码:

try
{
    system(script.c_str());
}
catch (exception& e)
{
    throw;
}
catch ( ... )
{
    ThrowException("Controller::LaunchScript()");
}

shell脚本位于/ usr / local / bin中,如下所示:

#!/bin/sh
ip_address='192.168.0.1'
remote_usr='xxusrxx'
remote_cmd='/usr/local/bin/remote_application'

cmd="ssh -X "$remote_usr"@"$ip_address" \""$remote_cmd"\""
eval $cmd &

有任何想法或建议吗?

更新1:

当我查看使用' ps -ef'运行的进程时,C ++ / Qt程序和启动器脚本都会显示,但是' ssh -X'确实。当我重新启动我的C ++ / Qt程序时,它会抛出一个错误"已经在使用的地址"就像我过去尝试启动应用程序同时已经运行另一个实例一样。

更新2:

我可能会越来越深入兔子洞,但我现在正在关注sudo + xauth问题和解决方案。当前失败的尝试是添加:

export XAUTHORITY=/home/xxusrxx/.Xauthority
sudo -E -u xxusrxx

此外,看起来挂起的C ++ / Qt进程已经不存在了。一种可能性是跟踪应用程序"清理"启动时失效的进程。

2 个答案:

答案 0 :(得分:1)

由于您使用Qt,因此没有理由使用system调用,并且没有理由使用帮助程序脚本。最后,将system调用包装在try-catch块中是没有意义的,因为它不会引发异常。它是一个返回结果的C函数。

您可以使用QProcess::startDetached,您的代码不会等待任何事情:

QString ip_address="192.168.0.1"
QString remote_usr="xxusrxx"
QString remote_cmd="/usr/local/bin/remote_application"

if (!QProcess::startDetached("ssh", QStringList()
  << "-X" << QString("%1@%2").arg(remote_usr).arg(ip_address)
  << remote_cmd)
  ThrowException("Controller::LaunchScript()");

您可以类似地启动脚本,但是对于脚本来说真的没有意义。

答案 1 :(得分:1)

尝试将所有文​​件描述符(stdin,stdout,stderr)重定向到/ dev / null。

在shell脚本中,更改为:

eval $cmd >/dev/null 2>&1 &

其实我不知道为什么你需要eval,只需直接调用ssh:

ssh -X "$remote_usr"@"$ip_address" "$remote_cmd" >/dev/null 2>&1 &

&gt; / dev / null - 显然,这会重定向标准输出。
2&gt;&amp; 1 - 这会将标准错误(fd 2)重定向到我们之前重定向到/ dev / null的标准输出(fd 1),所以现在它们都被重定向到/ dev / null <登记/> &amp; - 分支到后台会自动将stdin重定向到/ dev / null

等效地,直接在C ++ / Qt中,你可以在QStringList的末尾添加另一个字符串,就像Kuba Ober给你看的那样

<< remote_cmd << ">/dev/null 2>&1")

回复您的更新:

您在更新中说&#34;当我查看使用&#39; ps -ef&#39;运行的进程时, C ++ / Qt程序或启动器脚本显示< / strong>,但是&#39; ssh -X&#39;确实。 &#34;

这是否意味着您不再有卡住的线程/进程?

此外你说&#34;当我重新启动我的C ++ / Qt程序时,它会抛出一个错误&#34;已经在使用的地址&#34;&#34;
我想是这样的,因为当你在前一个ssh客户端仍在运行时(并转发X11)再次启动ssh时,它再次连接到远程服务器上,它告诉sshd服务器打开一个端口来监听X服务器连接,并且然后它抱怨该端口(或interface_address:端口组合)已被使用。 如果您不需要多个ssh连接,那么简单的解决方案就是在启动应用程序之前终止现有的ssh连接。否则,您必须研究如何强制sshd绑定到另一个端口或类似的东西。也许以其他用户身份登录会自动解决问题。

但是这里有一个很重要的一点:我真的不具备X11转发的经验,所以我只是假设它是如何工作的,我就写得很好。我可能错了。