我正在使用程序synergy和ssh隧道
它可以工作,我只需要打开一个控制台,输入这两个命令:
ssh -f -N -L localhost:12345:otherHost:12345 otherUser@OtherHost
synergyc localhost
因为我很懒,我制作了一个Bash-Script,只需点击一下图标即可运行:
#!/bin/bash
ssh -f -N -L localhost:12345:otherHost:12345 otherUser@OtherHost
synergyc localhost
上面的Bash-Script也可以,但是现在我也想通过一次鼠标点击杀死synergy和ssh隧道,所以我必须将synergy和ssh的PID保存到文件中以便以后杀死它们:
#!/bin/bash
mkdir -p /tmp/synergyPIDs || exit 1
rm -f /tmp/synergyPIDs/ssh || exit 1
rm -f /tmp/synergyPIDs/synergy || exit 1
[ ! -e /tmp/synergyPIDs/ssh ] || exit 1
[ ! -e /tmp/synergyPIDs/synergy ] || exit 1
ssh -f -N -L localhost:12345:otherHost:12345 otherUser@OtherHost
echo $! > /tmp/synergyPIDs/ssh
synergyc localhost
echo $! > /tmp/synergyPIDs/synergy
但是这个脚本的文件是空的。
如何获得ssh和协同作用的PID?
(我尽量避免ps aux | grep ... | awk ... | sed ...
组合,必须有一种更简单的方法。)
答案 0 :(得分:72)
快速摘要:无效。
我的第一个想法是你需要在后台启动进程以获得$!
的PID。
像
这样的模式some_program &
some_pid=$!
wait $some_pid
可能会做你需要的......除了那个ssh不会在前台再问一下passphrases。
那么,你可能需要一些不同的东西。ssh -f
可能会产生一个新的进程,你的shell无论如何都无法通过它来调用它。理想情况下,ssh本身会提供一种将PID写入某个文件的方法。
答案 1 :(得分:56)
对pgrep
,pkill
,ps | awk
等用户充满敬意,有一个 多 更好方式。
考虑一下,如果您依靠ps -aux | grep ...
来查找流程,则会面临发生冲突的风险。您可能有一个不太可能的用例,但作为一般规则,它不是可行的方法。
SSH提供了一种管理和控制后台进程的机制。但是像许多SSH一样,它是一个先进的"功能,很多人(似乎从这里的其他答案)不知道它的存在。
在我自己的用例中,我在家里有一个工作站,我希望在我的办公室留下一个连接到内部网络上的HTTP代理的隧道,另一个允许我快速访问co上的管理界面的工作站。 - 定位服务器。这就是你如何创建从家里发起的基本隧道:
$ ssh -fNT -L8888:proxyhost:8888 -R22222:localhost:22 officefirewall
$ ssh -fNT -L4431:www1:443 -L4432:www2:443 colocatedserver
这些导致ssh到背景本身,使隧道保持打开状态。但如果隧道消失了,我就会陷入困境,如果我想找到它,我必须解析我的流程列表并回家我已经得到了#34;正确的" ssh(如果我意外地发起了多个看似相似的东西)。
相反,如果我想管理多个连接,我使用SSH的ControlMaster
配置选项以及-O
命令行选项进行控制。例如,我的~/.ssh/config
文件中包含以下内容,
host officefirewall colocatedserver
ControlMaster auto
ControlPath ~/.ssh/cm_sockets/%r@%h:%p
上面的ssh命令在运行时会在~/.ssh/cm_sockets/
中留下spoor,然后可以提供对控件的访问,例如:
$ ssh -O check officefirewall
Master running (pid=23980)
$ ssh -O exit officefirewall
Exit request sent.
$ ssh -O check officefirewall
Control socket connect(/home/ghoti/.ssh/cm_socket/ghoti@192.0.2.5:22): No such file or directory
此时,隧道(和控制SSH会话)已经消失,无需使用锤子(kill
,killall
,pkill
等。
将此内容反馈给您的用例......
您正在建立隧道,您希望syngergyc
通过TCP端口12345与syngergys
进行通信。为此,我会执行以下操作。
在~/.ssh/config
文件中添加条目:
Host otherHosttunnel
HostName otherHost
User otherUser
LocalForward 12345 otherHost:12345
RequestTTY no
ExitOnForwardFailure yes
ControlMaster auto
ControlPath ~/.ssh/cm_sockets/%r@%h:%p
请注意,命令行-L
选项使用LocalForward
关键字处理,并且包含Control {Master,Path}行以确保在建立隧道后能够控制。
然后,您可以将bash脚本修改为以下内容:
#!/bin/bash
if ! ssh -f -N otherHosttunnel; then
echo "ERROR: couldn't start tunnel." >&2
exit 1
else
synergyc localhost
ssh -O exit otherHosttunnel
fi
-f
选项指示隧道,在ControlPath上留下一个套接字以便稍后关闭隧道。如果ssh失败(可能是由于网络错误或ExitOnForwardFailure
),则无需退出隧道,但如果没有失败(else
),则会启动synergyc然后隧道在退出后关闭。
您可能还想查看是否可以使用SSH选项LocalCommand
从ssh配置文件中直接启动synergyc
。
答案 2 :(得分:21)
刚刚遇到这个帖子,想提一下“pidof”linux实用程序:
$ pidof init
1
答案 3 :(得分:16)
您可以使用lsof显示在localhost上侦听端口12345的进程的pid:
lsof -t -i @localhost:12345 -sTCP:listen
示例:
PID=$(lsof -t -i @localhost:12345 -sTCP:listen)
lsof -t -i @localhost:12345 -sTCP:listen >/dev/null && echo "Port in use"
答案 4 :(得分:12)
ssh -f -N -L localhost:12345:otherHost:12345 otherUser@otherHost
echo `ps aux | grep -F 'ssh -f -N -L localhost' | grep -v -F 'grep' | awk '{ print $2 }'` > /tmp/synergyPIDs/ssh
synergyc localhost
echo `ps aux | grep -F 'synergyc localhost' | grep -v -F 'grep' | awk '{ print $2 }'` > /tmp/synergyPIDs/synergy
(你可以将grep集成到awk中,但我现在太懒了)
答案 5 :(得分:9)
您可以删除-f
,这会让它在后台运行,然后使用eval
运行它并自行强制它到后台。
然后你可以抓住pid
。请务必将&
放在eval
声明中。
eval "ssh -N -L localhost:12345:otherHost:12345 otherUser@OtherHost & "
tunnelpid=$!
答案 6 :(得分:4)
对于synergyc(以及大多数其他尝试自我控制的程序)而言,这是一个特例。用$!可以工作,除了synergyc在执行期间执行一个clone()系统调用,它将为它提供一个新的PID,而不是bash认为的那个。如果你想绕过这个以便你可以使用$ !,那么你可以告诉synergyc留在forground然后背景它。
synergyc -f -n mydesktop remoteip &
synergypid=$!
synergyc还会执行一些其他操作,比如自动启动,如果您尝试管理它,可能需要关闭。
答案 7 :(得分:3)
另一种选择是使用pgrep来查找最新ssh进程的PID
ssh -fNTL 8073:localhost:873 otherUser@OtherHost
tunnelPID=$(pgrep -n -x ssh)
synergyc localhost
kill -HUP $tunnelPID
答案 8 :(得分:2)
您可以使用以下行查看绑定到本地端口的ssh过程:
netstat -tpln | grep 127\.0\.0\.1:12345 | awk '{print $7}' | sed 's#/.*##'
它使用localhost上的端口12345 / TCP返回进程的PID。因此,您无需过滤ssh
的所有ps
结果。
如果您只需要检查 if 该端口是否已绑定,请使用:
netstat -tln | grep 127\.0\.0\.1:12345 >/dev/null 2>&1
如果没有绑定,则返回1
;如果有人正在侦听此端口,则返回0
。
答案 9 :(得分:0)
基于@ghoti的非常好的答案,这是一个更简单的脚本(用于测试),利用 SSH控制套接字而无需额外配置:
#!/bin/bash
if ssh -fN -MS /tmp/mysocket -L localhost:12345:otherHost:12345 otherUser@otherHost; then
synergyc localhost
ssh -S /tmp/mysocket -O exit otherHost
fi
只有在成功建立隧道后才会启动 synergyc
,一旦synergyc
返回,隧道本身就会关闭。
虽然解决方案缺乏适当的错误报告。
答案 10 :(得分:0)
这里有很多有趣的答案,但是没有人提到SSH 确实的手册页描述了这种情况! (请参见TCP FORWARDING
部分)。他们提供的解决方案更加简单:
ssh -fL 12345:localhost:12345 user@remoteserver sleep 10
synergyc localhost
详细信息:
-f
,它才会启动连接,然后才分叉到后台(与ssh ... &; pid=$!
的解决方案不同,其中ssh发送到后台,并且在隧道创建之前之前执行了下一条命令) )。在远程计算机上,它将运行sleep 10
,它将等待10秒钟,然后结束。synergyc localhost
。它将连接到隧道,然后SSH将知道该隧道正在使用中。sleep 10
命令将完成。但是synergyc
仍在使用该隧道,因此SSH 在隧道释放之前(即,synergyc
关闭套接字之前)不会关闭连接连接。synergyc
时,它将释放隧道,而SSH将依次终止自身并关闭连接。此方法的唯一缺点是,如果我们使用的程序由于某种原因而关闭并重新打开连接,则SSH将在连接关闭后立即关闭隧道,并且该程序将无法重新连接。如果存在问题,则应使用@doak's answer中所述的方法,该方法使用控制套接字正确终止SSH连接,并使用-f
确保在SSH派生到后台时创建隧道。