![如何使用 ssh-agent 作为包装程序?](https://linux22.com/image/147502/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%20ssh-agent%20%E4%BD%9C%E4%B8%BA%E5%8C%85%E8%A3%85%E7%A8%8B%E5%BA%8F%EF%BC%9F.png)
我正在尝试将awesome
Windows 管理器作为ssh-agent
.当我使用startx
(ssh-agent startx
)时,它起作用了。但现在我正试图让它在lightdm
.
lightdm
开始/usr/bin/xinitrcsession-helper
:
#!/bin/bash
exec $HOME/.xinitrc
~/.xinitrc
:
ssh-agent awesome
我得到的是:
509 1 lightdm /usr/bin/lightdm
526 509 Xorg /usr/lib/Xorg :0 -seat seat0 -auth /run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch
877 509 lightdm lightdm --session-child 14 21
1003 877 xinitrcse /bin/bash /usr/bin/xinitrcsession-helper
1028 1003 awesome awesome
1029 1028 ssh-a ssh-agent awesome
并且set | grep SSH
什么也不返回。
然后我启动另一个xterm
( ssh-agent xterm
) 并且它起作用了:
1636 1 xterm xterm
1638 1636 bash bash
1651 1638 vim vim
9435 1651 xterm xterm
9447 9435 ssh-a ssh-agent xterm
9449 9435 bash bash
10464 9449 ps ps -eHo pid,ppid,comm,args
10465 9449 les less
这里奇怪的是,它ssh-agent
是它启动的程序的子程序。你能解释一下吗?
我该如何运行awesome
以便之后启动的程序可以看到ssh-agent
?
UPD关于ssh-agent
作为它运行的命令的子级。这是为了能够替换command
为ssh-agent command
。所以,ssh-agent
分叉,父级exec
是command
.
UPD我的错,我是用来xbindkeys
启动的xterm
,而前者恰好是之前启动的ssh-agent
。像,xbindkeys && ssh-agent awesome
。因此,它没有SSH_*
要传递给的变量xterm
。或者说这是我最可能的解释。当使用awesome
内置工具启动时xterm
,环境变量会正确传递。
答案1
在您的更新中,您提到您xterm
从xbindkeys
跑步开始
xbindkeys && ssh-agent awesome
bindkeys
不会有 SSH 相关的环境,因此xterm
也不会。
为了解决这个问题,我建议
eval "$(ssh-agent)"
xbindkeys && awesome
xbindkeys
现在,这将为和设置变量(这很可能是您需要和想要的),但当您注销时awesome
它不会自动终止该进程。ssh-agent
为此,您可以使用 (with bash
),
eval "$(ssh-agent)"
trap 'eval "$(ssh-agent -k)"' EXIT
xbindkeys && awesome
或类似的东西。ssh-agent -k
一旦 shell 退出或被TERM
,HUP
或终止,这将调用它将杀死代理INT
。
eval
在 的输出上运行ssh-agent -k
只会取消设置 SSH 变量,并且可能不需要它(因为脚本无论如何都会退出),因此可以将陷阱设置为仅运行ssh-agent -k >/dev/null
。
ssh-agent
作为它启动的命令的子进程的事情看起来奇怪的。
ssh-agent
分叉实际的代理进程,然后用它应该运行的命令的进程替换原始进程(使用exec()
)。结果是原始进程(xterm
在第二个进程树中)是代理的父进程:
/*
* Fork, and have the parent execute the command, if any, or present
* the socket data. The child continues as the authentication agent.
*/
if (D_flag || d_flag) {
log_init(__progname,
d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO,
SYSLOG_FACILITY_AUTH, 1);
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf("echo Agent pid %ld;\n", (long)parent_pid);
fflush(stdout);
goto skip;
}
pid = fork();
if (pid == -1) {
perror("fork");
cleanup_exit(1);
}
if (pid != 0) { /* Parent - execute the given command. */
close(sock);
snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
if (ac == 0) {
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
SSH_AGENTPID_ENV_NAME);
printf("echo Agent pid %ld;\n", (long)pid);
exit(0);
}
if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
perror("setenv");
exit(1);
}
execvp(av[0], av);
perror(av[0]);
exit(1);
}
(子进程然后继续执行其余代码)
例如,这允许您终止代理而不会对您想要运行的命令产生太大影响。