- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我知道要做端口转发,命令是ssh -L
。我还使用其他选项来装饰它。因此,例如,最终的完整命令可能如下所示 ssh -fCNL *:10000:127.0.0.1:10001 127.0.0.1
。输入密码后一切正常。
然后,因为不是只有一个端口需要转发,我决定把这个工作留给 shell 脚本,并使用 expect(tcl) 来提供密码(都一样)。
虽然对expect没有很深的理解,但还是借助网络写出了代码。该脚本成功生成 ssh 并提供正确的密码。但是当我尝试使用 ps -ef | 进行检查时,我最终发现没有这样的过程。 grep ssh
和 netstat -anp | grep 10000
.
我为 ssh 提供了 -v
选项,输出似乎没问题。
那么问题出在哪里呢?我通过 Internet 进行了搜索,但大多数问题都与端口转发无关。我不确定使用expect是否合适,而我只想让脚本自动提供密码。
这是脚本。
#!/bin/sh
# Port Forwarding
# set -x
## function definition
connection ()
{
ps -ef | grep -v grep | grep ssh | grep $1 | grep $2 > /dev/null
if [ $? -eq 0 ] ; then
echo "forward $1 -> $2 done"
exit 0
fi
# ssh-keygen -f "$HOME/.ssh/known_hosts" -R "127.0.0.1"
/usr/bin/expect << EOF
set timeout 30
spawn /usr/bin/ssh -v -fCNL *:$1:127.0.0.1:$2 127.0.0.1
expect {
"yes/no" {send "yes\r" ; exp_continue}
"password:" {send "1234567\r" ; exp_continue}
eof
}
catch wait result
exit [lindex \$result 3]
EOF
echo "expect ssh return $?"
echo "forward $1 -> $2 done"
}
## check expect available
which expect > /dev/null
if [ $? -ne 0 ] ; then
echo "command expect not available"
exit 1
fi
login_port="10000"
forward_port="10001"
## check whether the number of elements is equal
login_port_num=$(echo ${login_port} | wc -w)
forward_port_num=$(echo ${forward_port} | wc -w)
if [ ${login_port_num} -ne ${forward_port_num} ] ; then
echo "The numbers of login ports and forward ports are not equal"
exit 1
fi
port_num=${login_port_num}
## provide pair of arguments to ssh main function
index=1
while [ ${index} -le ${port_num} ] ; do
login_p=$(echo ${login_port} | awk '{print $'$index'}')
forward_p=$(echo ${forward_port} | awk '{print $'$index'}')
connection ${login_p} ${forward_p}
index=$((index + 1))
done
这里是脚本的输出
spawn /usr/bin/ssh -v -fCNL *:10000:127.0.0.1:10001 127.0.0.1
OpenSSH_7.2p2 Ubuntu-4ubuntu2.10, OpenSSL 1.0.2g 1 Mar 2016
...
debug1: Next authentication method: password
wang@127.0.0.1's password:
debug1: Enabling compression at level 6.
debug1: Authentication succeeded (password).
Authenticated to 127.0.0.1 ([127.0.0.1]:22).
debug1: Local connections to *:10000 forwarded to remote address 127.0.0.1:10001
debug1: Local forwarding listening on 0.0.0.0 port 10000.
debug1: channel 0: new [port listener]
debug1: Local forwarding listening on :: port 10000.
debug1: channel 1: new [port listener]
debug1: Requesting no-more-sessions@openssh.com
debug1: forking to background
expect ssh return 0
forward 10000 -> 10001 done
最佳答案
这应该适合你:
spawn -ignore SIGHUP ssh -f ...
另一种解决方法是:
spawn bash -c "ssh -f ...; sleep 1"
ssh -f
调用 daemon()使自己成为守护进程。参见 ssh.c在源代码中:
/* Do fork() after authentication. Used by "ssh -f" */
static void
fork_postauth(void)
{
if (need_controlpersist_detach)
control_persist_detach();
debug("forking to background");
fork_after_authentication_flag = 0;
if (daemon(1, 1) == -1)
fatal("daemon() failed: %.200s", strerror(errno));
}
int
daemon(int nochdir, int noclose)
{
int fd;
switch (fork()) {
case -1:
return (-1);
case 0:
break;
default:
_exit(0);
}
if (setsid() == -1)
return (-1);
if (!nochdir)
(void)chdir("/");
if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
(void)dup2(fd, STDIN_FILENO);
(void)dup2(fd, STDOUT_FILENO);
(void)dup2(fd, STDERR_FILENO);
if (fd > 2)
(void)close (fd);
}
return (0);
}
在父进程中的 _exit()
和 setsid()
之间存在竞争条件(不确定这里的术语是否正确)> 在子进程中。这里 _exit()
总是先完成,因为“函数 _exit() 终止调用进程立即”和 setsid()重量要重得多。所以当父进程退出时,setsid()
还没有生效,子进程还在和父进程在同一个 session 中。根据apue book (我指的是 2005 版,第 10 章:信号),SIGHUP
如果 session 领导者终止也会生成。在这种情况下,信号被发送到每个进程在前台进程组中。”
简而言之:
ssh
。此处,ssh
将在新 session 中运行并成为 session 负责人。ssh -f
调用 daemon()
。父进程( session 领导者)调用 _exit()
。此时,子进程仍在 session 中,因此它会收到 SIGHUP
,其默认行为是终止进程。解决方法的工作原理:
spawn -ignore SIGHUP
) 是明确要求进程忽略 SIGHUP
,这样它就不会终止。 bash -c 'sshh -f ...; sleep 1'
,bash
将成为 session 负责人,sleep 1
最后会防止 session 负责人过早退出。所以在 sleep 1
之后,子 ssh
进程的 setsid()
已经完成并且子 ssh
已经 在新的进程 session 中。您可以通过以下修改(在 ssh.c 中)编译 ssh 并验证:
static int
my_daemon(int nochdir, int noclose)
{
int fd;
switch (fork()) {
case -1:
return (-1);
case 0:
break;
default:
// wait a while for child's setsid() to complete
sleep(1);
// ^^^^^^^^
_exit(0);
}
if (setsid() == -1)
return (-1);
if (!nochdir)
(void)chdir("/");
if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
(void)dup2(fd, STDIN_FILENO);
(void)dup2(fd, STDOUT_FILENO);
(void)dup2(fd, STDERR_FILENO);
if (fd > 2)
(void)close (fd);
}
return (0);
}
/* Do fork() after authentication. Used by "ssh -f" */
static void
fork_postauth(void)
{
if (need_controlpersist_detach)
control_persist_detach();
debug("forking to background");
fork_after_authentication_flag = 0;
if (my_daemon(1, 1) == -1)
// ^^^^^^^^^
fatal("my_daemon() failed: %.200s", strerror(errno));
}
关于linux - ssh 端口转发 ("ssh -fNL") 无法通过 expect spawn 自动提供密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63951895/
我开发了一个具有基本安全性的 Spring Boot 应用程序。我有两个具有相同路径和不同 http 方法的端点。当我使用默认密码/使用 application.yml 中给出的密码包含基本安全性时,
我的代码是这样的: 或者,像这样: 如果我首先列出 webm 源,Firefox 4 会播放它,但 Firefox 3.6 也会尝试播放它(但会失败,因为它不支持 webm)。
我希望提供一个泛型类型作为类型参数而不首先将其解析为具体类型。换句话说,我正在寻找一种方法来指定从基类继承时可以使用的类型映射函数。 示例(不正确的)语法,希望比我能解释得更好: abstract c
我在 .NET 中编写了一些桌面应用程序,它们既提供了用于正常使用的前端 GUI,也提供了用于其他需求(例如扩展、调度、自动化、高级使用等)的命令行界面。命名两个可执行文件的最佳做法是什么,因为它们构
我最近在这里思考了很多关于屏幕抓取以及它可能是一项什么样的任务。所以我提出以下问题。 作为网站开发人员,您是否会公开简单的 API 以防止用户抓取屏幕,例如 JSON 结果? 然后这些结果可以实现缓存
我正在为一个项目使用 Dojo 1.9,但我不明白 dojo.provide 的正确替代方案与传统风格相比,AMD 风格。我正在阅读 this文档页面。 很明显,这就是旧语法映射到新语法的方式: 旧
我正在开发一个 Angular 应用程序。当我使用 ng serve 正常运行它时,它运行没有任何错误.但是,当我运行 ng build --prod ,它给出了以下错误。 ERROR in Ille
我有一个 Mac 应用程序。在我的 Mac 应用程序中,我的屏幕之一有一个包含文本字段的 scrollView。在同一屏幕上,我有一个需要提供打印选项的按钮。可以打印文本字段的文本。打印按钮应调用 M
我已经成功地为普通媒体文件提供媒体文件,但是当我尝试提供管理媒体文件时,我失败了。请帮我找出问题所在,因为我已经尝试解决问题几个小时但没有运气(也一直在谷歌搜索并阅读有关提供静态文件的 django
我正在尝试创建一个简单的错误处理项目,它会在收到错误(例如 404、422 或 500)后为 JSON 提供错误数据。我使用来自 this 的代码网站,但它不适合我。 我实际上有这两个类: 基本 Co
假设我有一个名为 Number 的类(class),我打算对 Number 进行大量相等比较对象。我担心通用 Number::equals(Object o) 的“开销”(类比较等...)方法。在这种
假定以下情况: 对等方A只希望将音频流发送给对等方B 对等B只希望将视频流发送给对等A 从而, 与创建报价 var sdpConstraints = { “必填”:{ 'OfferToReceiveA
因为我有一些角度,所以我想检查角度模数 360°: double angle = 0; double expectedAngle = 360; angle.Should().B
这是我的程序中构建的 monad 堆栈: type Px a = ReaderT PConf (State PState) a 其中 PConf 和 PState 是保存应用程序的配置和状态的任意数据
因为我有一些角度,所以我想检查角度模数 360°: double angle = 0; double expectedAngle = 360; angle.Should().B
我有一个小程序需要以某些权限运行,这意味着加载时会显示一条警告消息。如果用户拒绝警告消息,我想重定向到错误页面并解释发生了什么。有什么办法可以做到这一点吗? 我研究过让计时器运行并在特定时间段后重定向
从我可以从 Firebase 文档中推断出,似乎需要服务器来提供静态内容(html和 javascript),所以你需要有一台托管机器和一个静态内容服务器在某处启动并运行,或某些服务托管静态站点。 对
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 3 年前。 Improv
我的项目根目录的静态文件夹中有一个文本文件。 我想提供它,所以我创建了: @csrf_exempt def display_text(request): content = retur
我目前正在研究指针,为了进一步理解我正在尝试使用指针将两个数值数组连接成一个。代码如下所示。 #include void concat(int **pa,int **pb,int **pc) {
我是一名优秀的程序员,十分优秀!