0

I was messing around with echo and was trying stuff like echo ~. When I was trying to use $ to substitute environment variables I accidentally tried echo $$. Surprisingly instead of an empty line I get a six-digit number, 269523. I kept trying the same command and the number did not change. However when I tried it a few hours later the number changed but it was still a six-digit number. What is the meaning of echo $$? Are there any other chars like $ that have special meaning in the context of environment variables?

Kusalananda
  • 333,661

3 Answers3

0

It's simply the pid of the current shell:

$ tr '\0' '\n' < /proc/$$/cmdline
bash
0

The $ parameter (whose value you are outputting with echo by prefixing it with another $) is a special parameter (not an environment variable) in all POSIX and POSIX-like shells (like bash and zsh and others). It holds the process ID (PID) of the current shell.

This parameter is defined in the POSIX standard (see Special Parameters) as

$
Expands to the decimal process ID of the invoked shell. In a subshell (see Shell Execution Environment), $ shall expand to the same value as that of the current shell.

Since both echo "$$" and (echo "$$") output the same PID even though the second command is executed in a subshell, the bash shell has introduced the BASHPID variable, which is updated in subshells. This is also not an environment variable.

The reference above will also list the eight special parameter that may be the ones you are asking about. Note that the text below is using my own words and that you should look at the standard or in the manual for the specific shell you're using to get a more specific description.

  • @: "$@" is the list of positional parameters (usually the command line arguments to the current script or function).
  • *: "$*" is a single string with the positional parameters concatenated using the first character of $IFS (usually a space) as the delimiter.
  • #: "$#" is the number of positional parameters.
  • ?: "$?" is the exit status of the most recently executed command.
  • -: "$-" is a string containing the currently set shell options.
  • $: "$$" is described above (the PID of the current shell).
  • !: "$!" is the PID of the most recently started asynchronous job ("background process").
  • 0: "$0" is the name of the current shell or shell script. This is used in diagnostic messages.
ilkkachu
  • 138,973
Kusalananda
  • 333,661
0

In Bourne-like and csh-like shells (and perl), $ is a special parameter that expands to the id of the process that executed the shell interpreter. So $$ is parameter expansion syntax to expand the value of that parameter.

It's not easy to look for in the documentation as $ is also a special character in the search syntax of info and the less pager (typically used for paging man pages) at least and $ occurs everywhere in the manual.

In the zsh manual, you'll find it in the Parameters Set By The Shell section (info -n 'Parameters Set By The Shell' zsh):

$
The process ID of this shell. Note that this indicates the original shell started by invoking zsh; all processes forked from the shells without executing a new program, such as subshells started by (...), substitute the same value.

In the bash manual, in the Special Parameters section:

'$'
($$) Expands to the process ID of the shell. In a '()' subshell, it expands to the process ID of the invoking shell, not the subshell.

Both zsh and bash manuals have an index entry for those (and most special variables and parameters) though, so you can get to it with:

info zsh '$'
info bash '$'

As both note, it's not necessarily the pid of the shell process interpreting (or executing since echo is builtin) that echo $$ command. For that, see the BASHPID special variable in bash and $sysparam[pid] in zsh.

Beware that in Bourne-like shells other than zsh, you'd need:

echo "$$"

as echo $$ without the quotes there is special syntax to invoke a split+glob operator which you don't need here. In practice though, you'll only see the difference if $IFS contains digits.

bash-5.0$ echo $$ "$$"
33664 33664
bash-5.0$ IFS=6
bash-5.0$ echo $$ "$$"
33  4 33664