There was a vote to close this as "unclear what you're asking". Apparently being thorough isn't a good thing, so I'll be terse:

When you SSH to a remote host: is it possible to execute a program directly instead of being executed under the user's default shell.

  • the network is air gapped
  • everyone on the network has shell access to every machine
  • IT can make whatever changes would be needed, provided those changes wouldn't increase the risk of someone getting a root shell (beyond what's already possible anyway).
  • As proof that something like it is possible: sftp, an ssh "subsystem", is able to execute without running the user's default shell, whereas the scp subsystem still uses it.
    • I tried implementing a subsystem, but it still executed under the user's default shell.

I don't think there is a good solution to this problem (short of convincing a large number of non-*nix people to abandon the crutch they've been leaning on for years), but I thought I'd put the question out there in hopes I'm mistaken.

Below is the less terse question.

In my office there's a large number of people (3-500+) all using a variety of strange and bizarre configurations. It's very hard to predict how the software we write will behave for a given user since their environment could totally violate our expectations.

To workaround this I changed our build to strip the user's environment so it couldn't affect the build, and based on the success of that strategy we further wrapped our software's execution in a shell script that does the same sort of thing.

Unfortunately, the launcher can still be affected by the user's environment. When it is executed remotely, the user's .cshrc/.login typically have a bunch of junk that causes long delays before the launcher even begins executing.

Normally I'd be inclined to say "fix your crap", but we're not talking about *nix-savvy people; this is a crutch they've leaned on for years and they're more inclined to continue to blame our software for their configuration issues.

In short, I'm looking for a way to completely short-circuit their goofy environment scripts.

To simulate this situation I set my default shell to tcsh and put hostname; sleep 10 in my .cshrc, then ran a few tests:

  • sftp does not print/sleep -- though, the target machine in that case was solaris where sftp is built into sshd, and I didn't think to test against a linux box. Running ptree against the process tree servicing the sftp connection shows it's not running under a shell.
  • scp prints the text & sleeps for 10s
  • every variant of executing commands on the remote host through ssh causes the command to run under the user's default shell; I tried:
    • The obvious -- pass a command in over ssh
    • command= in .ssh/authorized_keys
    • I made a custom "subsystem" in my personal linux /etc/ssh/sshd_config
  • Enabled PermitUserEnvironment on my machine to try setting SHELL
    • Didn't work at all: SHELL=/bin/bash ssh -o "SendEnv SHELL" localhost
    • Kinda worked: Use environment= or ~/.ssh/enviornment to set SHELL
      • It kinda worked in that SHELL was set, but it actually executes under my true default shell

I managed to use netcat to forward a shell over an existing ssh session, but that seems like using a sledge to crack an egg -- both messy and highly inappropriate.

One person in our organization suggested making another user that, through whatever means, everyone would be able to login as that user over ssh, then ::cloudy bubble solution with a lot of hand waving:: to get the program running as the original user.

I'm a little dubious about doing something like that. It may not be as bad as forwarding a shell with netcat, or something heavy-handed and brittle like temporarily renaming their .cshrc, but I'm still not fond of it.

Any suggestions are welcome.

  • Okay, so your software is invoked by running a shell script that strips the user's environment, and that works if that shell script is invoked locally, but it doesn't work if someone first SSH's into another machine and invokes the script there? Is that what you're saying?
    – Spiff
    Mar 17 '15 at 23:54
  • I'll edit to word it better. It still behaves properly, but if their .cshrc does a bunch of crap first (hence the sleep 10) it can create long delays. Mar 18 '15 at 0:01
  • Does the problematic user environment have anything in ~/.ssh/rc or /etc/ssh/sshrc?
    – Spiff
    Mar 18 '15 at 0:04
  • Nope. I've boiled it down to the simplest case with the example I gave: set your default shell to tcsh, put sleep 10 in your .cshrc, and try to ssh into that machine and run a command without causing .cshrc contents to be executed. Mar 18 '15 at 0:06
  • Is running an alternate shell at some point in the process possible? Something like ssh -t <host> sh? Or even something like ssh <host> csh -f [<command>]? (The docs I read says -f disables reading startup files.)
    – snapshoe
    Mar 22 '15 at 18:30

It should be possible to accomplish what you desire with a subsystem, but I am fairly certain it will require writing a custom sshd binary, as the OpenSSH code only provides the sftp subsystem, and merely sets up an extendable framework for additional definitions.


At least with Bash, ssh with the "-t" argument (e.g. ssh server1 -t '/foo/bar/script.sh') will run a remote command without executing "~/.bashrc" (the bash equivalent to "~/.cshrc/login").

  • That was one of the more irritating aspects of this problem. If the user's default shell is bash it wasn't difficult at all to avoid having .bashrc get sourced. csh and tcsh, on the other hand, are a little more irritating. Apr 16 '15 at 21:03
  • I dunno why I didn't upvote this question. While it didn't satisfy my needs, it's still potentially valuable to someone else. Jul 21 '15 at 15:37

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.