Environment-Variables

如何使用 ssh-agent 作為包裝程序?

  • March 14, 2019

我正在嘗試將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-agentforks 和 parentexeccommand.

UPD我的不好,我用xbindkeys的是 start xterm,而前者恰好是之前啟動的ssh-agent。就像在,xbindkeys && ssh-agent awesome。所以,它沒有SSH_*變數可以傳遞給xterm. 或者說是我最可能的解釋。當使用awesome’s 的內置工具啟動時xterm,環境變數是可以傳遞下來的。

在您的更新中,您提到您xterm從開始xbindkeys並從執行開始

xbindkeys && ssh-agent awesome

bindkeys不會有與 SSH 相關的環境,因此xterm也不會。

為了解決這個問題,我建議

eval "$(ssh-agent)"
xbindkeys && awesome

現在,這將為兩者設置變數xbindkeysand (這很可能是您需要和想要的),但是當您註銷時awesome它不會自動終止該程序。ssh-agent

為此,您可以使用 (with bash),

eval "$(ssh-agent)"
trap 'eval "$(ssh-agent -k)"' EXIT
xbindkeys && awesome

或類似的東西。這將呼叫ssh-agent -kwhich 將殺死代理,只要該 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);
}

(然後子程序繼續執行其餘程式碼)

例如,這允許您殺死代理而不會對您要執行的命令產生太大影響。

引用自:https://unix.stackexchange.com/questions/498488