Suppose that some variable FOO is defined (and export-ed) in the current environment.  Let me call this environment E0.Now, I log into some other Unix system using ssh.% ssh frobozz@for.example.comLet me call the environment of this newly established session E1.In general, FOO will not be defined in E1, and, in the exceptional cases where it is, in general its value will be set independently of the value of FOO in E0.How can I arrange things so that, upon log in via ssh, the variable FOO is set in E1 to the value it has in E0 (and, ideally, export-ed in E1 as well)?In case it matters, I'm using zsh for both E0 and E1.For the answer to this question, assume that I do not have any control over the configuration of the sshd process running on for.example.com.  This rules out, in particular, any solution that requires modifying /etc/ssh/sshd_config, or the like, on for.example.com.Also, assume that the value of FOO is not constant; it will change from one login session to another.  In particular, FOO may not be set in FOO at all, in which case it is ok if the effect on E1 is analogous to that of FOO= or export FOO= or unset FOO.UPDATE: I tried this% ssh frobozz@for.example.com FOO=$FOO env...and indeed, the output shows that FOO is set as specified.  But I have not figured out how to apply this idea when initiating a login session.  Specifically, if I run% ssh frobozz@for.example.com FOO=$FOO...the command just returns without establishing a connection (I figure that ssh interprets FOO=$FOO as the command to run on the remote host).  On the other hand, after I run this% ssh frobozz@for.example.com FOO=$FOO zsh...I never see the shell prompt from the remote host; the command just hangs there.  (I do, however, get a password prompt from ssh right before this.)  The same thing happens for other variants of the last command, such as% ssh frobozz@for.example.com FOO=$FOO /path/to/zsh% ssh frobozz@for.example.com FOO=$FOO env zsh% ssh frobozz@for.example.com env FOO=$FOO zsh% ssh frobozz@for.example.com env FOO=$FOO zsh -l% ssh frobozz@for.example.com 'env FOO=$FOO zsh'UPDATE2: Actually, what looked like hanging turns out to be that the prompt is not visible.  I can still run commands.  Also, the sequence of zsh initialization files that gets run upon login is different from normal, and (perhaps not suprisingly) the environment is substantially (and non-trivially, IOW above and beyond FOO) different from normal.UPDATE3: With help from dave_alcarin and meuh I found that this gets pretty close to what I am after:% ssh -t frobozz@for.example.com env FOO=$FOO zsh -l -sThere are still some non-trivial differences between the new environment and the normal one that I need to sort out, but this is pretty close to what I want.
How to pass environment variables to a new ssh-initiated login session?
ssh;zsh;environment variables
SSH has a feature to pass environment variables from the client to the server, but OpenSSH disables it in the default server configuration. There's one exception: TERM, which has a special place in the protocol; but communicating information via TERM is awkward because you have to be sure that the client will decode it.Nevertheless some servers are configured to let some environment variables through. For example, Debian configures the SSH server to allow all variables whose name begins with LC_. Usually these are locale variables, but you can put whatever you like.If the server isn't configured to allow any variable, you can pass them as part of he command, but there are a couple of wrinkles. The wrinkle you're hitting is that if you pass a command to ssh, then by default no terminal is created on the server. So ssh frobozz@for.example.com FOO=$FOO zsh does in fact run a shell, but that shell is connected to a pipe, not to a terminal, so it doesn't display a prompt or support command line edition. Nonetheless, you can type commands  try typing ls Enter, and exit Enter or Ctrl+D to exit. The solution is to explicitly tell SSH to open a terminal, with the -t option.ssh -t frobozz@for.example.com FOO=$FOO zshDepending on what your login shell is, you may want to runssh -t frobozz@for.example.com FOO=$FOO exec zshto avoid having an extra shell process that's the parent of that explicitly-invoked zsh.The second problem you haven't run into yet is quoting. The SSH protocol transmits a string which is executed by the remote shell. Here, you're passing the string consisting of FOO=, followed by the value of FOO, followed by a space and exec zsh. Thus the value of FOO is interpreted as a bit of shell source code, not as a string to store in the FOO variable. This makes a difference if the value contains characters that have a special meaning in shell syntax. You need to add an extra level of quoting. Assuming your local shell is zsh, you can use the q parameter expansion flag:ssh -t frobozz@for.example.com FOO=${(q)FOO} exec zshAnother difference with the straight case is that you're first running a login shell on the remote side, and then replacing it with a non-login shell. Since the chain starts with a login shell (this cannot be avoided), your .profile or .zprofile does get run; however the interactive instance of zsh is not a login shell, which might make a difference depending on the content of your dot files. The best solution for that is probably to avoid doing fragile things in your dot files. You can run zsh -l, but that runs a second login shell, which is prone to making more of a difference (though you can fix that, too, by making sure that your .profile or .zprofile is idempotent).