1. 23
  1.  

  2. 20

    On Linux:

    % ls -l /proc/$$/exe 
    lrwxrwxrwx 1 leah leah 0 Aug 29 17:28 /proc/3940/exe -> /usr/bin/zsh*
    
    1. 2

      FreeBSD:

      ❯ procstat -b $$
        PID COMM                OSREL PATH
      66249 zsh               1201000 /usr/local/bin/zsh-5.8
      

      If you’re in an old version after an upgrade of zsh, it’ll error with No such file or directory, which is one of the mechanisms I use for checkrestart.

    2. 6
      readlink -f "${SHELL}"
      

      Which works on most modern Unix-like systems except… macOS, where readlink(1) doesn’t have -f option ;^) so

      stat -F "${SHELL}"
      

      would probably be the closest thing.

      1. 9

        There’s no guarantee that $SHELL points to the currently running shell. It can point to literally anything.

      2. 3

        Another way on Linux:

        $ pstree -s -p $$
        systemd(1)───lightdm(1160)───lightdm(1317)───upstart(3532)───tmux(10127)───bash(14094)───pstree(14113)
        

        Geez, what’s with systemd AND upstart? This is on Ubuntu 16.04. OK I learned something …

        1. 2

          Another way is to be explicit in saying what shell the terminal app should run.

          1. 1

            Given that the article mentions brew, being explicit would break upon update + cleanup.

            1. 1

              I’ve been using brew for years and haven’t had a problem. /usr/local/bin/zsh is a symlink for a reason.

              1. 1

                Another way is to be explicit in saying what shell the terminal app should run.

                Thought you meant:

                /usr/local/Cellar/zsh/5.7.1/bin/zsh
                

                Did I misunderstand the above?

                1. 2

                  I think GP is referring to, in this example, /usr/local/bin/zsh.

          2. 2

            Simple, direct, portable…

            $ echo $0
            -/usr/bin/zsh
            
            1. 3

              You don’t get the whole path if the shell war launched via the user’s path:

              $ bash
              $ echo $0
              bash
              
              1. 3

                If it was launched via the path then which will tell you all you need to know.

            2. 1
              $SHELL
              ~ % echo $SHELL
              /usr/local/bin/zsh
              

              Eh, I don’t know. That tells me that it’s configured as my shell but does not necessarily tell me the location of the shell I’m currently typing in.

              I can hardly notice the difference. Since you have quit the terminal and started a new session, isn’t the shell you are using guaranteed to be the one configured?

              1. 9

                I can hardly notice the difference. Since you have quit the terminal and started a new session, isn’t the shell you are using guaranteed to be the one configured?

                I think this is the entire point of the article, “is it guaranteed?” The author is presenting a way to be sure your assumption about what is running is what is actually running, outside of the normal checks someone such as myself might run, such as echo’ing the $SHELL variable.

                If we abstract this a bit, let’s examine the value of a variable halfway through the execution of a program. We believe the value should not have changed, but without looking at the source code, that is a big assumption and the reason we’d be writing tests. The author just let us prove which actual executable was running.

                For a more concrete example, this screenshot is not edited at all. I clicked the ‘Terminal’ icon on my (admittedly Linux) desktop and immediately echo’d the $SHELL variable. It returns /bin/zsh. But when I use the author’s fuser suggestion, it shows there are no copies of that running, only /bin/bash! You can see all I had to do to fool echo $SHELL was set SHELL to be a new value in my .bashrc file.

                So to answer the question, no it is not guaranteed and the author just let you prove it.

                1. 1

                  I can see your point, but “The argument to chsh will be the shell for your subsequent logins as well as the content of $SHELL” is a promise made by the Unix-like environment. If you don’t trust the environment (which makes sense: maybe there is a rootkit), then you shouldn’t trust the output of fuser either, since it’s also part of the environment.

                  Your example of examining source code reminds me of this story. What if the tool you use to view the source also has a backdoor to hide a statement that changes the variable? :)

                  1. 3

                    I take your comment in the “:)” light it is intended and would like to meet you in the middle. I half considered going down the crazy extremes, but my example was more to point to the article giving us a way to start down the road of proving our assumptions, the same as we would prove the assumption that $x shouldn’t ever be negative in such-and-such a function.

                    I think the happy middle ground which allows that one might want to do more than echo $SHELL and less than cover my house in foil is the fact that I am often a fool and make silly decisions, often after saying “This shouldn’t hurt anything…” Occasionally I have found it very useful to validate my assumptions, only to realize that something I decided to do X months ago actually invalidated them. With how often that has proven true, I think the article’s offering of a way to prove the promise made by the Unix-like environment true, or false, is a very worthwhile thing, even if often it will not be needed.

                  2. 1

                    Thanks for this. I was afraid that what I was trying to convey wouldn’t quite come across. It’s a little meta in that I was curious if I could figure out the current path of the current process of the shell I was typing in.

                  3. 5

                    I just opened a terminal with my default shell being /bin/bash. I typed zsh, and at the zsh prompt typed, echo $SHELL. The response was, /bin/bash because that’s my login shell, and the one that spawned zsh.