我正在尝试实现一个启动2个ssh连接并执行需要root权限的脚本的工具。
这是一个非常简单的实现:
void* SshConnection(void* args)
{
char buffer[5000];
FILE* popenReturn = NULL;
//get the hostname to connect to
const char* hostname = (const char*)args;
snprintf(buffer, sizeof(buffer),
"/usr/bin/gnome-terminal -x bash -c \""
"ssh -t user@%s "
"-i /home/user/.ssh/key.key "
"\\\"/home/user/DoRootThings.bash\\\" ",hostname);
popenReturn = popen(buffer,"w");
pclose(popenReturn);
//...connect to the host again later on and look at results of DoRootThings.bash...
}
我使用此函数创建2个线程并将其分离
考虑到以上实现,我希望使用-i ssh选项提供的2个gnome终端可见,它们已登录到“用户”帐户。该脚本应该已经执行并且正在等待提供根密码,而两个执行线程都已在pclose()处停止,同时等待它们各自的gnome终端返回。
而是打开了两个gnome终端,它们正在等待root密码。其中一个线程的执行在pclose()处停止,而其他线程pclose()立即返回。然后,该线程继续查看DoRootThings.bash的结果,但没有任何结果,因为它仍在等待密码执行!
Solaris popen()和pclose()的手册页声称它们都是线程安全的。为了安全起见,我尝试了多种形式的锁定。
唯一有效的锁定方式是
pthread_lock(&lock1);
popenReturn = popen(buffer,"w");
pclose(popenReturn);
pthread_unlock(&lock1);
但这给我留下了一个单线程解决方案。
这是手册页错误并且popen()和pclose()线程不安全的情况吗?如果是这样,是否有可以解决此问题的锁定解决方案?
否则,我在执行中是否做错了什么?
注意:我最初使用system()而不是popen()和pclose(),但这不是线程安全的调用,因此system()的Solaris手册页推荐popen()和pclose()
在gnome-terminal
您的示例中,该命令可能不是一个不错的选择,我当然希望它只是一个示例。我不清楚您为什么不直接popen()
输入ssh
命令。更多关于gnome-terminal
以后。
你写
考虑到以上实现,我希望使用-i ssh选项提供的2个gnome终端可见,它们已登录到“用户”帐户。该脚本应该已经执行并且正在等待提供根密码,而两个执行线程都已在pclose()处停止,同时等待它们各自的gnome终端返回。
,但这不是我期望的。调用pclose()
应首先关闭流,另一端的进程在其标准输入上将其视为EOF。然后,该函数将等待子进程终止,但是该进程不应阻止任何从其标准输入读取的尝试。我通常希望两个 pclose()
电话都能迅速返回。
现在,我发现popen()
对于呈现GUI的程序(甚至与之类似的简单性)来说,这非常有问题gnome-terminal
,但gnome-terminal
由于以下事实,我倾向于猜测这特别棘手:
默认情况下,所有GNOME终端共享一个进程,从而减少了内存使用。可以通过使用该
--disable-factory
选项启动gnome-terminal来禁用它。
我相信您会理解,单进程行为可能会对期望创建和管理独立子进程的API造成严重破坏。我怀疑这是观察到的两个呼叫行为不同的原因。
此外,您应该检查函数调用的返回值,您的示例未演示该返回值。我不确定您popen()
和/或pclose()
是否应该发信号通知错误,但我认为这是一种很好的可能性。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句