Why Bash unable to find command even if $PATH is specified properly?
Solution 1
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:
- What's the conf file reading between login and non-login shell?
- Is there a ".bashrc" equivalent file read by all shells?
Solution 2
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
orsshd
.
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
Related videos on Youtube
SIGSEGV
Updated on September 18, 2022Comments
-
SIGSEGV over 1 year
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.
-
Bananguin over 11 yearsdoes just running
ydisplay
work? doesssh 127.0.0.1 /usr/app/cpn/bin/ydisplay
work? -
mnmnc over 11 yearsWhen 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.
-
SIGSEGV over 11 years@mnmnc, you said that .bashrc is not executed, but if I specifying $PATH in this file all works fine. How can it happen?
-
Ulrich Schwarz over 11 yearsJust 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. -
bsd over 11 yearsthis stackoverflow question might be of some help
-
Mikel over 11 years@SIGSEGV Actually,
~/.bashrc
is sourced. This fact is hidden futher down in the man page (and in Bash Reference Manual - Invoking Bash - Startup Files - Invoked by remote shell daemon).
-