4

Here is my script:

echo "Defining aliases"
echo $$
echo "
s=screen
v=vlock -a
j=jobs
" | sed '/^$/d' | while read alias
do
  echo $$
  alias "$alias"
  alias | wc -l
done

And here is its output:

parthian@computer$ . aliases 
Defining aliases
3744
3744
4
3744
5
3744
6
parthian@computer$ ps -p $$
PID TTY          TIME CMD
3744 pts/1    00:00:03 bash
parthian@computer$ alias | wc -l
3

I'm flummoxed. This is some of the most straightforward code I've ever written, and it's not doing what it's supposed to do.

EDIT: When I change the echo lines from echo $$ to echo $$ $BASHPID, the second PID ($BASHPID) is different inside the loop, but $$ remains the same throughout. Could this be the issue?

  • And it can't be that I'm not making enough blood sacrifices to Stallman's beard, because I sacrificed my last oxen just yesterday. – Parthian Shot Jun 24 '15 at 23:33
  • 1
    By putting the alias definitions on the RHS of a pipe (... | while read ...), you are implicitly confining their scope to a subshell, I think: see mywiki.wooledge.org/BashFAQ/024 – steeldriver Jun 24 '15 at 23:44
4

Don’t believe everything a computer tells you.

$ ps -p $$
PID TTY          TIME CMD
3744 pts/1    00:00:03 bash
$ ps -t pts/1
PID TTY          TIME CMD
3744 pts/1    00:00:03 bash
4285 pts/1    00:00:00 ps
$ echo foo | while read x
do
        ps -t pts/1
done
PID TTY          TIME CMD
3744 pts/1    00:00:03 bash
4287 pts/1    00:00:00 bash
4288 pts/1    00:00:00 ps
$ echo "$$, $BASHPID"
3744, 3744
$ echo foo | while read x
do
        echo "$$, $BASHPID"
        ps -t pts/1
done
3744, 4292
PID TTY          TIME CMD
3744 pts/1    00:00:03 bash
4292 pts/1    00:00:00 bash
4293 pts/1    00:00:00 ps

When you do some_command | while …, the shell puts the while loop into a subshell, but $$ continues to report the PID of the main (parent) process.  In bash, $BASHPID reveals the truth.

Consider doing

while read alias
do
  alias "$alias"
done << EOF
s=screen
v=vlock -a
j=jobs
EOF
  • Arrghhh.  I didn't see your edit until I had finished typing my answer.  Hope it helps anyway. – Scott Jun 25 '15 at 0:02
  • It does. Seems silly, but it hadn't occurred to me to use a heredoc- thanks! – Parthian Shot Jun 25 '15 at 0:16
  • 1
    It is also mentioned in bash man page: "[$]$ Expands to the process ID of the shell. In a () subshell, it expands to the process ID of the current shell, not the subshell." May be it also applies to subshells created for pipes – nitishch Jun 25 '15 at 1:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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