Exporting environment variable to user after login via su

I am struggling to work out what exactly the following alias does. I guess it is making the environment variable COUNTER available to the user nobody but the COUNTER=${COUNTER} preceding the ssh and the SendEnv COUNTER stump me. I have looked up the man pages but I am none the wiser.

alias run='COUNTER=${COUNTER} ssh nobody@localhost -o "SendEnv COUNTER"'

I’d like to rewrite this alias without ssh (because it has been disabled). Here is my attempt, but I am not sure if I have done the right thing if I don’t understand what the original alias does exactly.

alias run='su - nobody -c "export COUNTER=${COUNTER}"'
Asked By: Olumide

  1. Assigning a value to a variable on the same line / in the same statement before a program is run temporarily exports that variable to the environment for the program being run. It’s a way of exporting a variable for just one program – as soon as that program has been run, it’s no longer in the environment and will not affect or be available to any subsequent programs.

    COUNTER=${COUNTER} ssh ... sets $COUNTER to itself, temporarily exports it to the environment, then runs ssh.

    It was probably written by someone who doesn’t understand what curly braces or quoting are for because COUNTER=$COUNTER is 100% equivalent, and COUNTER="$COUNTER" would be even better, just because it’s good practice to double-quote variables unless you are absolutely certain that you do not want to and know exactly why you do not want to in that particular case. See $VAR vs ${VAR} and to quote or not to quote

  2. -o "SendEnv COUNTER" is an ssh option that tells ssh what local environment variables should be sent to the remote server. By default, only TERM is sent (and even then, only when a a pty is requested, e.g. an interactive ssh connection where you can type into the remote shell/program and see its output). From man ssh_config:


    Specifies what variables from the local environ(7) should be sent to the
    server. The server must also support it, and the server must be configured
    to accept these environment variables. Note that the TERM environment
    variable is always sent whenever a pseudo-terminal is requested as it is
    required by the protocol. Refer to AcceptEnv in sshd_config(5) for how
    to configure the server. Variables are specified by name, which may contain
    wildcard characters. Multiple environment variables may be separated by
    whitespace or spread across multiple SendEnv directives.

    See PATTERNS for more information on patterns.

    It is possible to clear previously set SendEnv variable names by prefixing
    patterns with -. The default is not to send any environment variables.

    Note that the remote server can and will ignore any sent variables unless it is configured to accept them. By default, it only accepts TERM. From man sshd_config:


    Specifies what environment variables sent by the client will be copied into
    the session’s environ(7). See SendEnv and SetEnv in ssh_config(5)
    for how to configure the client. The TERM environment variable is always
    accepted whenever the client requests a pseudo-terminal as it is required by
    the protocol.

    Variables are specified by name, which may contain the wildcard characters
    * and ?. Multiple environment variables may be separated by
    white‚Äźspace or spread across multiple AcceptEnv directives. Be warned
    that some environment variables could be used to bypass restricted user
    environments. For this reason, care should be taken in the use of this
    directive. The default is not to accept any environment variables.

    What this means is that, unless /etc/ssh/sshd_config on the remote server (actually localhost in your example, but that still qualifies as "remote"-ish enough for this purpose) is configured to accept the COUNTER variable, your COUNTER=${COUNTER} ssh nobody@localhost -o "SendEnv COUNTER" command wont do anything that just ssh nobody@localhost wouldn’t do.

  3. su - nobody -c "export COUNTER=${COUNTER} will run export COUNTER=${COUNTER} as user nobody, then exit (because the -c option tells su to run that command instead of just giving you a shell, it doesn’t run it before giving you a shell). Try COUNTER="$COUNTER" su - nobody instead. Or just export COUNTER so that it is in the environment for all programs you run.

Answered By: cas
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.