11

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.

7
  • 1
    does just running ydisplay work? does ssh 127.0.0.1 /usr/app/cpn/bin/ydisplay work?
    – Bananguin
    Commented Aug 23, 2012 at 8:36
  • @user1129682 Yes, ydisplay with full specified name works and just ydisplay works
    – SIGSEGV
    Commented Aug 23, 2012 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
    Commented Aug 23, 2012 at 8:58
  • 14
    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. Commented Aug 23, 2012 at 9:11
  • 2
    this stackoverflow question might be of some help
    – bsd
    Commented Aug 23, 2012 at 10:26

3 Answers 3

6

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:

1

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
-1

I've had this issue before. The reason is simple,

If you have two executable files sharing the same name located in two different directories, the shell will run the file that is in the directory that comes first in the $PATH

Source: How to Add a Directory to PATH in Linux

I had an app called Pointwise. When I checked where its executable was, I noticed the following thing:

:~> which pointwise
/usr/local/bin/pointwise

which was empty, but the installation created that directory. When I checked the $PATH, I had:

/usr/bin/path:/home/mendezj/bin:/usr/local/bin:/usr/bin:/bin:/opt/pbs/bin:/opt/sim_pkgs/working/apps/POINTWISE

Notice that I had changed /etc/profile and appended the actual path to the executable. To resolve the problem, I changed the location of the executable. I brought it to the beginning of the $PATH variable.

It was:

PATH="$PATH:/opt/sim_pkgs/working/apps/POINTWISE"

and I changed it to:

PATH="/opt/sim_pkgs/working/apps/POINTWISE:$PATH"

Problem solved because it looks at the first entry before going to /usr/local/bin.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .