如何使用 ssh-agent 作为包装程序?

如何使用 ssh-agent 作为包装程序?

我正在尝试将awesomeWindows 管理器作为ssh-agent.当我使用startxssh-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作为它运行的命令的子级。这是为了能够替换commandssh-agent command。所以,ssh-agent分叉,父级execcommand.

UPD我的错,我是用来xbindkeys启动的xterm,而前者恰好是之前启动的ssh-agent。像,xbindkeys && ssh-agent awesome。因此,它没有SSH_*要传递给的变量xterm。或者说这是我最可能的解释。当使用awesome内置工具启动时xterm,环境变量会正确传递。

答案1

在您的更新中,您提到您xtermxbindkeys跑步开始

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);
}

(子进程然后继续执行其余代码)

例如,这允许您终止代理而不会对您想要运行的命令产生太大影响。

相关内容