4

I just updated Cygwin and the new .bashrc contains this line right at the top:

echo "BEFORE TEST"
# If not running interactively, don't do anything
[[ "$-" != *i* ]] && return
echo "AFTER TEST"

I understand if not running interactive, you don't need to do anything, but my problem is that if I ssh with a command:

ssh localhost pwd

I see this:

BEFORE TEST

So, obviously, it fails the [[ "$-" != *i* ]] test and returns. Obviously ssh localhost pwd is a trivial example, but I expect .bashrc to be run all the way through if running a command through ssh. My actual automation runs commands remotely against this cygwin instance and is failing because the path (which is set by my .bashrc) is not getting set correctly.

Furthermore, can anyone explain what that test is actually doing? What is i? What is $- supposed to represent?

enzotib
  • 51,661
Lucas
  • 143

2 Answers2

7

If you run a single command (pwd in your case) through ssh, it is not an interactive shell, so the behavior is correct, in my opinion.

You should set your PATH in ~/.profile or ~/.bash_profile, not in ~/.bashrc.

As found in bash(1) man page:

   PARAMETERS
      (...)
      Special Parameters
          The shell treats several parameters specially.   These  parameters  may
          only be referenced; assignment to them is not allowed.
          (...)
          -      Expands  to  the  current option flags as specified upon invoca-
                 tion, by the set builtin command, or  those  set  by  the  shell
                 itself (such as the -i option).

So i contained in $- means that the -i option has been used (or automatically set by the shell, being interactive).

enzotib
  • 51,661
2

enzotib’s answer is correct (so upvoted) but I thought I’d complement it with details relating to shell start-up when the shell is launched via SSH.

Readers of Bash’s documentation might be wondering why there is need for .bashrc to check if it is running in an interactive shell given that a .bashrc is only sourced for interactive Bash shells. Nevertheless, the default ~/.bashrc included with most (if not all) Unix-like systems include some type of check (testing $- or $PS1) to ensure the current shell is interactive.

The reason for this is that Bash has a special case for remote shells. While non-interactive Bash shells don’t normally run ~/.bashrc commands at start-up, a special case is made when the shell is Invoked by remote shell daemon:

Bash attempts to determine when it is being run with its standard input connected to a network connection, as when executed by the remote shell daemon, usually rshd, or the secure shell daemon sshd. If Bash determines it is being run in this fashion, it reads and executes commands from ~/.bashrc, if that file exists and is readable. It will not do this if invoked as sh.

For more information, see my answer to Why does bashrc check whether the current shell is interactive?.