Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am specifying path to my command in the file /etc/profile:

export PATH=$PATH:/usr/app/cpn/bin

My command is located in:

$ which ydisplay 
/usr/app/cpn/bin/ydisplay

So, when I performing "echo $PATH" output is looks like:

$ echo $PATH
...:/usr/app/cpn/bin

And everything is OK, but when I am trying to launch my command via SSH I am getting error:

$ ssh 127.0.0.1 ydisplay
$ bash: ydisplay: command not found

But the my path is still present:

$ ssh 127.0.0.1 echo $PATH
...:/usr/app/cpn/bin

Please explain me why Bash unable to find ydisplay during SSH session and how to properly configurate SSH to avoid this issue.

More over, if I specifying $PATH in local file .bashrc in the current user all works correctly. But I want to modify only one file instead specifying a lot of files for each user. This is why I am asking.

share|improve this question
1  
does just running ydisplay work? does ssh 127.0.0.1 /usr/app/cpn/bin/ydisplay work? –  Bananguin Aug 23 '12 at 8:36
    
@user1129682 Yes, ydisplay with full specified name works and just ydisplay works –  SIGSEGV Aug 23 '12 at 8:52
    
When you are not logged (you do not have a remote session) but only sending a command remotely you dont have access to environment variables the same way because your .bashrc / .profile files are not executed. This is the reason as they are responsible for setting variables for current session. –  mnmnc Aug 23 '12 at 8:58
13  
Just a side note: ssh 127.0.0.1 echo $PATH does not do what you might think it does: the shell expands $PATH before ssh is even executed, so that doesn't prove or disprove anything. –  Ulrich Schwarz Aug 23 '12 at 9:11
2  
this stackoverflow question might be of some help –  bdowning Aug 23 '12 at 10:26

2 Answers 2

up vote 4 down vote accepted

tl;dr

Running ssh 127.0.0.1 ydisplay sources ~/.bashrc rather than /etc/profile. Change your path in ~/.bashrc instead.

details

The only time /etc/profile is read is when your shell is a "login shell".

From the Bash Reference Manual:

When bash is invoked as a login shell, ... it first reads and executes commands from the file /etc/profile

But when you run ssh 127.0.0.1 ydisplay, bash is not started as a login shell. Yet it does read a different startup file. The Bash Reference Manual says:

when ... executed by ... sshd. ... it reads and executes commands from ~/.bashrc

So you should put your PATH settings in ~/.bashrc.

On most systems, ~/.bash_profile sources ~/.bashrc, so you can put your settings only in ~/.bashrc rather than putting them in both files.

There's no standard way to change the setting for all users, but most systems have a /etc/bashrc, /etc/bash.bashrc, or similar.

Failing that, set up pam_env and put the PATH setting in /etc/environment.

See also:

share|improve this answer

Historically, the profile files (/etc/profile and ~/.profile) were invoked when you logged in (on the text console, what else?) and served many purposess:

  • Set environment variables and other parameters (e.g. umask) for the session.
  • Run extra programs at the start of the session (e.g. email notification).
  • Run the program for the session, if different from the shell (e.g. another shell or X Window).
  • Set terminal parameters (e.g. stty).
  • Set shell parameters (e.g. aliases).

All these purposes weren't identified as separate until later. Because the profile scripts may do things that only make sense in an interactive session (terminal interaction, start other programs), when remote shell invocation (rsh) was introduced, the makes of rsh decided not to invoke the remote shell as a login shell, so that the profile scripts aren't executed. (Some versions of rshd have an option to run the remote shell as a login shell.) Ssh copied this behavior in order to be a drop-in replacement for rsh.

If you want to have your profile scripts executed, you can invoke them explicitly.

ssh 127.0.0.1 '. /etc/profile; . ~/.profile; ydisplay'

Note the command . to load the profile scripts inside the shell: they are commands to be executed inside that shell, not an external program.

If you want to set an environment variable globally for all users, there is another method on many systems: instead of defining it in /etc/profile, define it in /etc/environment. This file is read through the pam_env module; most Linux distributions are set up to read it.

If your login shell is bash, there is a further possibility. Normally, you should not set environment variables in .bashrc (because they won't be set in X sessions except if you go through a terminal with an interactive shell, because they won't be set if you log in interactively on a text console or over ssh, because they'll override custom settings if you invoke a shell inside another program). However, bash has a strange feature that I've never understood: it reads ~/.bashrc in two unrelated circumstances:

  • in interactive shells that are not login shells;
  • in non-interactive shells that are not login shells, if bash thinks it has been invoked by rshd or sshd.

When you run a command over ssh, you are in the second case. You can arrange to have your profile read by reading /etc/profile and .profile from .bashrc. Include the following code in your ~/.bashrc:

case $- in
  *i*) :;; # this is an interactive shell, fine
  *) # This is not an interactive shell! This must be a non-interactive remote shell session.
    . /etc/profile; . ~/.profile
    return;;
esac
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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