我在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进程已经不存在了。一种可能性是跟踪应用程序"清理"启动时失效的进程。
答案 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转发的经验,所以我只是假设它是如何工作的,我就写得很好。我可能错了。