![通过 SSH 进行监控并在检测到更改时执行本地脚本](https://linux22.com/image/3520/%E9%80%9A%E8%BF%87%20SSH%20%E8%BF%9B%E8%A1%8C%E7%9B%91%E6%8E%A7%E5%B9%B6%E5%9C%A8%E6%A3%80%E6%B5%8B%E5%88%B0%E6%9B%B4%E6%94%B9%E6%97%B6%E6%89%A7%E8%A1%8C%E6%9C%AC%E5%9C%B0%E8%84%9A%E6%9C%AC.png)
我有一个环境,可以通过 Cygwin 通过 SSH 连接到 Linux 机器,但由于安全策略超出我的控制范围,所以不能以其他方式连接到 Linux 机器。
我需要在 Windows 计算机上自动执行任务,但通过从 Linux 计算机(即监视的文件夹或 Web 服务)拉取的脚本或参数来指示这些操作。
我如何构建它,以便我可以保持 SSH 连接打开,并在检测到此远程变量更改时,在 Windows 计算机上触发另一个 Cygwin 命令?
一个示例用例是带有参数的浏览器自动化。虽然我可以通过 git 存储库和每次运行前首先与最新代码同步的循环脚本来完成此操作,但我希望有更多的控制权,例如通过向下传递另一个变量或 shell 脚本来强制终止正在执行的线程。线。
更新:毕竟,还有另一种方法可以更改允许端口 22 连接的 Windows 防火墙,因此幸运的是不需要这种复杂的情况,但我喜欢下面列出的建议。
更新:看来这样的场景依然存在。虽然通过 SSH 直接访问系统允许执行任务,但这些任务是在 SSH 用户中沙箱化的,而不是我想要在其中运行 GUI 任务的网络域用户(本地 Cygwin 实例在域用户的域中执行时不存在问题)图形用户界面)。请参阅下面我的回答。
答案1
你可以在 Windows 机器上运行 sshd 吗?如果是,那么您可以打开一个隧道,以便 Linux 计算机可以向 Windows 计算机发送命令,如下所示:
ssh -R 2222:127.0.0.1:22 user@linuxmachine control-script
然后,control-script 将包含所有检查,如果必须在 Windows 计算机上执行某些操作,它将执行如下命令:
ssh -p 2222 user@localhost something.cmd
答案2
我使用了类似于 troydj 的答案,只需使用 watch 命令来执行一个“检查器”脚本,该脚本监视另一个脚本的存在并在发现时执行它。
在 Windows 的 Cygwin 上
watch -n 5 ~/checker.bash
检查器.bash
#!/bin/bash
if [ -f myscript.bash ]; then
sh ~/myscript.bash
else
echo 'checking...'
fi
myscript.bash(通过 SSH 启动 Visual Studio 2012 的示例)
#!/bin/bash
/cygdrive/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio\ 11.0/Common7/IDE/devenv.exe
rm myscript.bash
在 Linux 机器上,我可以开发并创建脚本。然后,当我希望它们在登录用户 GUI 的 Windows 上执行时,我将脚本复制到该myscript.bash
位置,该位置一旦被“检查器”脚本发现(由命令循环watch
),就会在本地执行。
在本例中,我将最后一行添加到脚本中,以便在执行后将其自身删除。
这对于我的目标来说非常有效。如果没有这样的解决方法,让 Cygwin 通过 SSH 连接驱动特定 Windows 用户帐户中的进程通常很棘手。
答案3
如果您Expect
的本地 Cygwin 机器上有,则可以使用它ssh
进入远程 Linux 机器并监视假脱机目录中的作业。当检测到新工作时,Expect 脚本可以暂停ssh
,在 Cygwin 系统上运行本地命令,然后恢复 ssh。它可能看起来像这样(作为基本的第一遍):
#!/usr/bin/expect
set timeout 10
log_user 1
spawn bash --login
expect -re {.*\$} ;# Assumes a dollar sign in your prompt on local box
send "ssh remoteuser@your_remote_linux_box\r"
expect "*word:*"
send "REMOTE_PASSWORD\r" ;# Bad security practice!! For illustration purposes only.
expect -re {\r\n.*\$} ;# Assumes a dollar sign in your prompt on your remote box
puts "Connected to remote system"
set i 0
while {$i < 5} { ;# For now, we just loop 5 times. You might loop forever...
send "ls ~/TasksSpoolDir | wc -l\r";
expect -re "\r\n(\[0-9\]+)\r"
set taskcount $expect_out(1,string)
sleep 1
if { $taskcount } {
# Inspect remote job files from spool directory, for example, to determine what you want to do locally
send "\r~\032" ;# Send ~CTRL-Z to ssh
expect "Stopped"
send "pwd; ls; echo Do local tasks now. Remove remote job files from spool directory...\r"
sleep 1
send "fg\r" ;# Resume ssh.
sleep 1
send "\r\r"
expect -re {\r\n.*\$} ;# Assumes a dollar sign in your prompt on your remote box
}
incr i
sleep 1; # Sleep however long between checks for new work from spool directory
}
send "exit\r"
expect -re {.*closed}
puts "Connection to remote host closed..."
send "exit\r"
expect "*"
puts "Local bash process closed..."
wait
exit 0