我正在运行 OSX Mountain Lion,远程服务器是 CentOS 6。我的本地机器上有几个脚本,我想在远程服务器上运行它们,为此,我想编写一个通过 ssh 连接的脚本,该脚本将第二个脚本作为参数执行。这样,我可以自然地编写 bash 脚本,而不必担心 ssh 及其带来的所有问题,并且相同的脚本也可以在我的本地机器上重新使用。例如,
执行远程命令
!#/bin/bash
ssh -t -t jeff@remoteserver 'bash -s' < $1
制作目录 (注意 sudo)
!#/bin/bash
sudo mkdir -p /some/path/to/a/new/location
而这个想法就是
./exec_remote.sh make_dir.sh
我遇到过很多问题,其中大部分我都能够克服。但是,现在当我执行上述脚本时,终端会挂起几分钟,远程目录不会创建,也没有错误消息。
此外,由于我没有调用logout
,我仍然打开了 ssh 终端,并且所有后续命令(即ls
)都完全冻结。我让一个ls
运行了 70 分钟,然后才将其中断。注意:我实际上并不关心之后运行的命令;我只是将此作为错误的症状。
我该如何纠正这个问题?或者,有没有更好的方法来解决这个问题?
编辑
如果我更新make_dir.sh
脚本以创建不需要的目录sudo
,则脚本将按预期正常执行。远程运行 sudo 命令是否存在已知问题?也许仅限于 CentOS?
答案1
尝试在后台远程运行脚本,将 std out 和 std err 重定向到日志文件。为了让您的 shell 返回(即不会“在脚本运行时长时间锁定”),您需要使用 nohup 以及重定向所有管道:StdOut、StdIn、StdErr。例如:
ssh jeff@remoteserver 'nohup make_dir.sh >> /tmp/log_file 2>&1 </dev/null &'
上述命令将让您登录到远程服务器并在后台运行 make_dir.sh,同时将 StdOut 和 StdErr 重定向到 /tmp/log_file。StdIn 从 /dev/null 重定向。否则,ssh 将挂起,直到脚本完成。
您提到该脚本需要很长时间才能完成。以这种方式运行脚本应该允许您再次登录并进一步检查正在发生的事情。
答案2
您执行 ssh 的方式存在一个根本缺陷,即:您只有一个 stdin。由于您使用 读取脚本<
,因此 stdin 会被“填充”脚本内容。并与您的输入(在本例中为您的密码)合并。这无法正常工作。
所以我认为唯一可行的方法是:你必须将脚本复制到远程服务器,然后启动一个只执行该脚本的 ssh 命令。因此,大致如下:
/bin/bash #!/bin/bash USERHOST=jeff@remoteserver ssh -o ControlMaster=yes -o ControlPersist=3600 -o ControlPath=/tmp/ssh-master-$USER-%r@%h:%p -Nf $USERHOST 陷阱“ssh -o ControlPath = / tmp / ssh-master-$USER-%r@%h:%p $USERHOST -O exit”退出 TEXEC=$(ssh $USERHOST mktemp) scp $1 ${USERHOST}:${TEXEC} ssh -t -t $USERHOST $TEXEC
此脚本打开与远程服务器的可共享连接(因此您只需输入一次 SSH 密码),然后复制您的 shell 脚本并最终使用常规命令执行它ssh
,这允许它分配 TTY,从而允许以(相对)安全的方式输入您的密码sudo
。在包装器脚本的末尾,共享连接通过陷阱关闭exit
。
答案3
做就是了
ssh -t -t jeff@remoteserver $1
运行命令(确保它是可执行的)然后退出。
bash -s 保持 bash 会话打开。
您可能需要 $* 而不是 $1,以便您可以将参数传递给您正在调用的脚本
答案4
我想我明白你想要什么。在远程机器上执行本地文件。
通过管道将本地文件 cat 到远程 bash
例如测试
$ echo "ls -l" | ssh jeff@remoteserver "bash "
在脚本中
cat $1 | ssh jeff@remoteserver "bash "