4

When I want to start (or restart) ssh-agent, it gives me a few commands that I should run by doing eval $(ssh-agent). Of course this fails for fish, since it gives syntax for bash or csh.

The commands look like:

SSH_AUTH_SOCK=/var/folders/v4/c116f_790t7g58lh3jbr7_vm0000gq/T//ssh-L95xhmGl9FZo/agent.36846; export SSH_AUTH_SOCK;
SSH_AGENT_PID=36847; export SSH_AGENT_PID;
echo Agent pid 36847;

or for csh:

setenv SSH_AUTH_SOCK /var/folders/v4/c116f_790t7g58lh3jbr7_vm0000gq/T//ssh-Tf8etHZfP9k3/agent.36873;
setenv SSH_AGENT_PID 36874;
echo Agent pid 36874;

The csh version runs without complaint when I do eval (ssh-agent -c), and then echo $SSH_AGENT_PID $SSH_AUTH_SOCK gives the expected output. However, new shells do not keep those variables. What does setenv do? clearly it sets variables somehow, but it's nowhere in the documentation. If I start a new terminal, the variables are lost, so I'm not sure they're exported?

I just found that setenv is a fish function, with definition set -gx, so I suppose it sets the variable as a global variable and exports it. I don't have a good understanding of the variable scope, so is the the appropriate thing for the ssh-agent variables?

For context, I'm doing this based on instructions at github. I've been using an ssh key for github for years and never did the ssh-agent or ssh-add thing, but I noticed it while setting up on a new computer. It also seems that os x is running ssh-agent on its own (or something else I set up long in the past), because there exists $SSH_AUTH_SOCK already. So maybe running this is not important? ssh-add does run without complaint even without running ssh-agent.

2
  • At a fish prompt, type type setenv Commented Sep 3, 2015 at 17:10
  • Thanks @glenn, I discovered that with functions setenv, see my edit. type is nice, though. It seems to be some combination of which and functions.
    – askewchan
    Commented Sep 3, 2015 at 17:11

3 Answers 3

3

I wrote this a while ago:

function ssh_agent --description 'launch the ssh-agent and add the id_rsa identity'
    if begin
            set -q SSH_AGENT_PID
            and kill -0 $SSH_AGENT_PID
            and grep -q '^ssh-agent' /proc/$SSH_AGENT_PID/cmdline
    end
        echo "ssh-agent running on pid $SSH_AGENT_PID"
    else
        eval (command ssh-agent -c | sed 's/^setenv/set -Ux/')
    end
    set -l identity $HOME/.ssh/id_rsa
    set -l fingerprint (ssh-keygen -lf $identity | awk '{print $2}')
    ssh-add -l | grep -q $fingerprint
        or ssh-add $identity
end

To emphasize, I use create universal variables from the ssh-agent output, and setenv will create global variables

5
  • What is kill -0? I don't see that in the man page. And /proc doesn't exist on my system (maybe os x doens't have it).
    – askewchan
    Commented Sep 3, 2015 at 17:48
  • kill -0 pid returns successfully if that pid is a running process, error otherwise. I use /proc to check that a running pid is actually a ssh-agent process: there are other ways to do this (pgrep, parsing ps output) Commented Sep 3, 2015 at 18:12
  • This works on mac os x if I change the /proc/ line to: and ps -p $SSH_AGENT_PID | grep -q 'ssh-agent'
    – askewchan
    Commented Sep 3, 2015 at 22:34
  • 1
    I recomment changing the grep pattern to '[s]sh-agent' so you don't accidentally match the grep command itself in the ps output. Commented Sep 4, 2015 at 15:08
  • This works on cygwin :P
    – Zardoz89
    Commented Jul 6, 2016 at 10:11
2

Consider to use

fish_ssh_agent

Utility functions to start your ssh agent when using fish shell. You will only need to run ssh-add and type your password once, after the running ssh_agent should do the work for you. Need to run once, environment variables shared between sessions.

Installation
wget https://gitlab.com/kyb/fish_ssh_agent/raw/master/functions/fish_ssh_agent.fish -P ~/.config/fish/functions/
Usage
fish_ssh_agent

SOURCE

Put this to ~/.config/fish/functions/fish_ssh_agent.fish

function __ssh_agent_is_started -d "check if ssh agent is already started"
   if begin; test -f $SSH_ENV; and test -z "$SSH_AGENT_PID"; end
      source $SSH_ENV > /dev/null
   end

   if test -z "$SSH_AGENT_PID"
      return 1
   end

   ps -ef | grep $SSH_AGENT_PID | grep -v grep | grep -q ssh-agent
   #pgrep ssh-agent
   return $status
end


function __ssh_agent_start -d "start a new ssh agent"
   ssh-agent -c | sed 's/^echo/#echo/' > $SSH_ENV
   chmod 600 $SSH_ENV
   source $SSH_ENV > /dev/null
   true  # suppress errors from setenv, i.e. set -gx
end


function fish_ssh_agent --description "Start ssh-agent if not started yet, or uses already started ssh-agent."
   if test -z "$SSH_ENV"
      set -xg SSH_ENV $HOME/.ssh/environment
   end

   if not __ssh_agent_is_started
      __ssh_agent_start
   end
end
1

This works for me on FreeBSD 10.2. Add the following to ~/.config/fish/config.fish:

if begin; test -z (command pgrep ssh-agent); and not test -S $SSH_AUTH_SOCK; end
    eval (command ssh-agent -c | sed -E 's/^setenv (.+);$/set \1; set -Ux \1;/')
end

The first set, without the -Ux, sets the environment variables for the first terminal that launches ssh-agent. The second set, with -Ux, sets the environment variables for all other terminals.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .