使用ssh,如何在不退出的情况下在远程计算机上运行命令?


29

通常,如果您像这样将命令传递给ssh

ssh me@example.com 'some-command.sh'

您将获得一个非交互式会话,并且在运行命令(或脚本或任何其他内容)后,ssh将立即退出。如何获得交互式会话,但如何运行从本地计算机指定的命令。例如,我希望能够打开屏幕并重新启动特定的屏幕会话:

ssh me@example.com 'screen -r 12345'

但这是不允许的,并返回错误“必须连接到终端”。我认为这实际上意味着“必须从交互式外壳程序中调用此命令”。

再举一个例子,我在工作中使用大量机器,经常需要我使用一个共享帐户才能执行某些操作的权限(是的,我知道:不好的主意,但不要怪我,我没有设置这些功能)方式),并且通常将ksh作为默认外壳。我想登录,切换到bash(或zsh),并获取我自己帐户的.bash_profile(或.zshrc)。如果我可以建立一个交互式ssh会话并将命令传递给远程计算机以在登录时运行,这将很容易。

我会发布一个非常笨拙(未经测试)的解决方案,但我希望有人知道更好的方法。

更新:对于那些没有意识到这一点的人,我不打算手工完成所有这些,因此,告诉我打开一个交互式会话然后手动进行,实际上并没有解决任何问题。

第二次更新:再次尝试澄清:我正在尝试在服务器上运行(任意)命令(在客户端上以编程方式指定),但随后打开了一个交互式会话,该会话受那些编程命令所执行的任何操作的影响。


echo "command" | ssh user@remote_host
laggingreflex 2015年

2
您是否错过了问题的“不退出”部分?我很确定在命令完成后这将退出。
iconoclast

Answers:


26

您可以尝试使用以下命令来启动bash并在使用ssh时获取您自己的配置文件:

ssh  -t hostname "bash --rcfile ~user/.bashrc"

4
+1。该-t开关还可以解决发问者的问题screen
修补

3
可以在不关闭连接的情况下与任意命令一起使用吗?如果我尝试ssh -t www.dev "echo 'hi there'"执行该命令,则连接将立即关闭。
iconoclast 2013年

11

基于dogbane的答案,完整的解决方案如下所示:

ssh -t user@server 'cd /a/great/place; bash'

在这里,我用于-t强制分配伪终端,这是交互式外壳程序所必需的。然后,我在服务器上执行两个命令:首先是在打开交互式外壳程序之前要执行的操作(在本例中,将目录更改为特定的文件夹),然后是交互式外壳程序本身。bash看到它有一个伪终端并进行交互响应。

单引号确保将整个内容作为要由默认外壳程序运行的命令传递到远程服务器。

再次感谢dogbane提供必要的线索-t。我曾经使用来解决此问题expect,这肯定是用大炮杀死了老鼠。(:


2

试试这个解决方案。

echo "command" | ssh user@remote_host

登录名是交互式的,您的命令将像在交互式命令行上键入命令一样传递。会话就像您键入的内容一样终止

ssh user@remote_host 'command'

3
如果会话在命令完成后终止,则不会回答该问题。在执行命令后,整个命令将保留一个交互式会话,不仅仅是通过来向服务器发送命令ssh
iconoclast 2013年

这至少对于模拟一个不需使用您自己的bash文件即可执行命令的interactve很有好处-t。+1
laggingreflex 2015年

0

使用ssh -X使用termIO cmds。

另外-您可以像“ ssh'source〜/ .bashrc && cd && do'”那样链接您的cmd。


但是在完成整个链后,我没有剩下的互动会话了,对吗?它仍然关闭,对吗?
iconoclast

您是否愿意详细说明termIO解决方案?
iconoclast

0

为什么不在远程系统上安装detach并使用:

ssh -t user@example.com "/home/user/bin/detach ls"

这样会运行“ ls”并然后离开我进行交互式会话吗?如果我运行'source .somefile'而不是'ls'以获得一些别名和功能,该怎么办?它们将在我的交互式会话中可用,还是在其他会话中运行?
iconoclast

不行,由于的缘故detachls它无法保持会话打开,并且会在不打印的输出的情况下断开连接,ls但仍会运行。
Dan D.

我正在尝试在服务器上运行(任意)命令(在客户端上以编程方式指定),但随后打开了一个交互式会话,该会话受那些编程命令所执行的任何操作的影响。因此,如果我正确地理解了您,对我没有帮助。
iconoclast

0

laggingreflex的答案很接近...我将其更改如下:

echo "command\n$(cat -)" | ssh user@remote_host

不幸的是,您不太可能喜欢这种工作方式,因为“ cat”会将其写入标准输出的行缓冲起来...如果我们创建一个名为“ echo-cat”的脚本,它看起来像这样:

{
  echo "${@}"
 #cat buffers & won't flush to stdout immediately
 #cat -
  IFS='\n'
  while read line
  do
        echo "${line}"
  done
}

没有缓冲我们将得到相同的结果:

echo-cat "command" | ssh user@remote_host

那可能会使您更接近目标...


0

这很笨拙,而且未经测试,但我认为应该可以。

创建一个名为(例如)remote-starter的脚本,该脚本在user @ host参数之后接受带引号的参数:

remote-starter user@example.com 'some-command.sh arg1 arg2'

该脚本应首先将加引号的命令(不带引号)保存在.onetime远程计算机上名为(例如)的文件中,然后运行常规的ssh命令,这次不传递任何要在远程计算机上运行的命令。(如果从脚本中运行ssh user@example.com,则可以运行exec ssh user@example.com。)

为此,远程计算机必须.onetime从其.bash_profile或.zshrc或其他任何源中获取资源。运行后.onetime,应将其删除.onetime,因此在您下次进行常规登录后,该文件将不会运行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.