I have a shell script which I simply cannot do without: bar from Theiling Online

I use SSH a lot and on a variety of *nix servers. However, I am not a system administrator and usually don't have the time or privileges to install it on every server I connect to.

It is apparently a very portable sh script and has command line options to export itself as a shell function, which got me thinking: Could I use one of OpenSSH's subjectively obscure features to export it everywhere I go?

My first thought was to assign the source to an environment variable like BAR = "cat -v" and then execute it on the other side as `$BAR`, but 1) I can't even get the cat example to to work locally, 2) I don't know how to put the script's actual multiline source into an environment variable and 3) I have yet to see a machine with PermitUserEnvironment enabled.

I guess I could even do with an ssh option to write a file called ~/bar at logon, but a more volatile solution would be better.

Calling wget http://.../bar at logon would be unacceptable.

Any ideas?

P.S. Putty-specific solutions, though I doubt any would exist, are also fine.

Edit: The reason I don't want wget and other file-based solutions is that I don't want to leave a mark since sometimes I connect as other people's users or root. I also don't want every server I connect to making an HTTP request. I want this to have as little overhead as possible.


I have not tried any of this, but you may find what you are looking for with a combination of options.

Check out man 5 ssh_config for:

  1. SendEnv - you could store bar into an environment variable, but you then need to execute it. For example BAR=$(bar -D), then in the remote shell eval $BAR, having sent the variable over - I know it is one step short of what you want but, hey, progress;
  2. LocalCommand - not sure that helps, unless you can do an unattended ssh, but then I can't see it working either;

The only other option I see would be to hack into the source code for your client and introduce a feature which executes a command immediately after log-on (such as eval $BAR for instance, this could be an ssh_config option called RemoteCommand for instance), after the environment variables have been sent and before waiting for input from the user.


In fact I have an idea for the full answer (untested):

In the SendEnv, make sure to send PS1 and DEFINEBAR, and set PS1 to eval $DEFINEBAR ($DEFINEBAR should contain your function and set PS1 to a reasonable value afterwards). The caveat is that the server needs to be configured to accept environment variables, which is unlikely to be the case for a default or secure set-up. So back to square one if your setup does not allow for this.

  • All the machines in question seem to have AcceptEnv = LANG LC_* which means I might have to use a hack like using LC_BAR instead of BAR. LocalCommand seems to be configured locally and I was able to execute an echo, but I don't know how to export an environment variable (or two) from there. export x=y didn't work. – aib Feb 28 '11 at 12:12
  • BTW LocalCommand worked exactly like how you thought RemoteCommand would. – aib Feb 28 '11 at 12:13
  • @aib, So this means LocalCommand is executed before the shell starts, or as a sub-shell. Bugger. Not sure how to get beyond this. You could probably get LocalCommand to create a file with your script then, can you? – asoundmove Feb 28 '11 at 12:32
  • I see. I was hoping I was doing something wrong, such as not giving the --really-really parameter to export. I guess it has to be a file, then? I'll have to leave a mark on every server I connect to? – aib Mar 1 '11 at 9:33

Here's a variation on Dennis Williamson's solution that doesn't require that you be able to ssh from the remote machine back to your local machine. On the local system:

$ bar -D | ssh user@host 'cat > barfunc'
$ ssh user@host

On the remote system:

$ . ./barfunc

I tested the components of that but not using bar, which I don't have.

  • This is probably what I'll end up doing. – aib Feb 28 '11 at 11:57

In your question, you said using wget was unacceptable. Are you against wget or against copying the file? I don't think you're going to be able to get the functionality you want unless you somehow copy the file to the local machine.

Maybe you can to source the file (but i'm fairly certain this would fail). The command would like this the following, depending on shell:

source mymachine:/home/user/bar
. mymachine:/home/user/bar

if you're against wget specifically, you can try scp, with setting up ssh keys it would mean a passwordless experience.

mkdir ~/bin; scp -r myserver:/home/user/bin/* ~/bin; chmod u+x ~/bin

Personally, what worked for me was to put my shell scripts into a subversion repository and then check out the repo on every machine. if i updated the script, i can check it back in svn, and then update it on other machines.

  • +1 for source control, which I suggested to our sysadmin. Unfortunately, I'm not a sysadmin and the machines may not always have access to our office network where the repository would be stored. It might be a good idea to put my favorite shell scripts on the net somewhere, though, updated via git and downloadable through HTTP. – aib Feb 28 '11 at 11:57

This may give you a start:

On your local system:

$ bar -D > ~/barfunc
$ ssh user@host     # or similar

On the remote system:

$ func=$(scp yourname@yoursystem:~/barfunc /dev/stdout)
$ eval "$func"
$ bar_cat somefile ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.