Why does running echo $$ in bash return a number like 7190, while running echo $ only returns a $?
- 54,268
- 25
- 157
- 179
- 3,728
- 7
- 29
- 55
-
If you use `set -x` to enable tracing of commands, you'll see the shell expands `$$` before running `echo` on it. This is your clue to go look for `$$` in the `bash` man page. (`set +x` to disable tracing again). – Peter Cordes Aug 08 '17 at 00:22
-
1If you want to echo a literal `$$`, quote the args to echo: `echo 'foo $$ bar'` prints exactly that, with multiple spaces. – Peter Cordes Aug 08 '17 at 00:23
-
1VTR - Looking at the close duplicate there is no reference in the question to "$$" nor is it in any of the answers. Using this close as duplicate logic we could close every question in AU that has a `$` in it which is probably thousands. – WinEunuuchs2Unix Aug 08 '17 at 02:24
-
@WinEunuuchs2Unix There a number of special variables in bash. There's no point to having a question on each of them. And [it is in the answers](https://askubuntu.com/a/521683/158442). – muru Aug 08 '17 at 05:32
-
1The part of this question that interests me most is why "running `echo $` returns `$`"--that is, why is `$` by itself is treated literally, rather than being considered a bad substitution like `${}`? (`$` by itself can't be expanded, and is treated literally; `${}` can't be expanded, and is an error.) If this is reopened, perhaps additional answers will be posted to explain that. I can sort of address this--`$x` is actually a short form of `${x}` *where `x` is a valid parameter name*--but I suspect others might be able to explain it from a more historical, formal, or practical perspective. – Eliah Kagan Aug 08 '17 at 05:44
-
@EliahKagan if you can address that part of the question, I'll add the final reopen vote myself. – muru Aug 08 '17 at 06:23
3 Answers
Convention.
$$: Expands to the process ID of the shell. In a () subshell, it expands to the process ID of the invoking shell, not the subshell (see the link to the manual below).
rinzwind@schijfwereld:~$ echo $$
3244
rinzwind@schijfwereld:~$ ps -ef |grep 3244
rinzwind 3244 3237 0 19:06 pts/0 00:00:00 /bin/bash
Very useful when coding software. And it can be used as a crude (mktemp would be the better method) way of creating temp files
1 $ has no special meaning so it gives you what echo always does: return it.
There is a manual page dedicated to this (3.4.2 Special Parameters).
- 293,910
- 41
- 570
- 710
-
-
6
-
4
-
-
I don't believe there's anything at all crude about using it to create temp files. It has the advantage that one can look at the file name, test to see if the process is running, and if it is not, safely remove the file. And that's one reason I like using $$ in the names of my temp files. – Monty Harder Aug 07 '17 at 18:29
-
4@MontyHarder: Predictable names (like `/tmp/myscript.$$`) for tmp files are usually a security vulnerability. See http://www.linuxsecurity.com/content/view/115462/151/ for why `mktemp` is the right way, if you can't avoid needing a tmp file in the first place. Including the PID of your script in the `mktemp` template is a good idea, though, for the reason you point out. – Peter Cordes Aug 08 '17 at 00:18
-
@PeterCordes Monty's point is similar to one of my challenges in that when you need to track down a temp file created by a spawned sleeping process and remove it whilst killing the process it is helpful when the file name is static and not dynamic as in `mktemp`. Sorry if that sounded convoluted.... – WinEunuuchs2Unix Aug 08 '17 at 02:32
-
1"Very useful when coding software: `ps -ef | grep $$`." -- This is going to give false positives rather frequently. – hvd Aug 08 '17 at 17:21
-
@hvd The process searching for its own PID would just `ps -fp $$` etc. anyway, and a process searching for another process's PID would have extracted it from the temp file name, and `ps -fp ${Extracted_PID}` or whatever. – Monty Harder Aug 09 '17 at 17:53
In bash to state using a variable we use $, using $$ with the first dollar sign we are saying that I want to use a variable and using the second one we are telling that the name of that variable is actually a $. it's actually a naming convention, and this variable contains the process id of the current shell.
As you asked in the comments with $$$$ you are returning the same process id twice.
There are other variables too (From here):
$1,$2,$3, ... are the positional parameters."$@"is an array-like construct of all positional parameters,{$1, $2, $3 ...}."$*"is the IFS expansion of all positional parameters,$1 $2 $3 ....$#is the number of positional parameters.$-current options set for the shell.$$pid of the current shell (not subshell).$_most recent parameter (or the abs path of the command to start the current shell immediately after startup).$IFSis the (input) field separator.$?is the most recent foreground pipeline exit status.$!is the PID of the most recent background command.$0is the name of the shell or shell script.
- 54,268
- 25
- 157
- 179
-
1Don't tell Windy but this time I'm up-voting your answer which I think covers a wide range of special characters. I think I'll get a sportsmanship badge down the line but, greed aside, I really do like your all encompassing succinct answer. You might want to post this same answer on: [Special variables in bash](https://askubuntu.com/questions/521677/special-variables-in-bash) – WinEunuuchs2Unix Aug 08 '17 at 02:39
-
@WinEunuuchs2Unix I wrote an alternative there, not sure if its add anything helpful to that question, anyway ... ;) – Ravexina Aug 08 '17 at 06:06
Here is a real life application of $$ taken from Lock Screen Timer:
# Check if lock screen timer already running
pID=$(pgrep -f "${0##*/}") # All PIDs matching lock-screen-timer name
PREVIOUS=$(echo "$pID" | grep -v ^"$$") # Strip out this running copy ($$$)
if [ "$PREVIOUS" != "" ]; then
kill "$PREVIOUS"
rm ~/.lock-screen-timer-remaining
zenity --info --title="Lock screen timer already running" --text="Previous lock screen timer has been terminated."
fi
In this code snippet the line:
PREVIOUS=$(echo "$pID" | grep -v ^"$$") # Strip out this running copy
uses the current running process ($$) to remove it (denoted by not -v) from the list of all processes running under the same name (lock-screen-timer in this case).
If there was a previous running copy the code kills it and delete the work file it was using.
- 99,709
- 34
- 237
- 401
-
In `grep -v ^"$$"`, `^` doesn't mean "not"--`v` does. `-v` causes `grep` to display non-matching lines instead of matching ones. In a regular expression, `^` only means "not" when it appears immediately following the opening `[` of a [character class](http://www.regular-expressions.info/charclass.html). For example, `[^ac]` matches any character besides `a` or `c`. Outside character classes, `^` is an [anchor](http://www.regular-expressions.info/anchors.html) that matches the empty string at the beginning of a line. For example, `^x` matches an `x` that appears at the beginning of a line. – Eliah Kagan Aug 08 '17 at 00:47
-
@EliahKagan Thank you for correcting me. I've changed the parameter to `-v`. The `^` was probably necessary because a Desktop link to the script had a modified version of the program name. But for the life of me I honestly can't remember the exact reason now. It was sooo long ago I last debugged the script... Anyway thanks again for your experienced insight. – WinEunuuchs2Unix Aug 08 '17 at 01:11
-
I think you were right to include `^`. If the current PID is 2345, `grep -v "$$"` will drop `2345` as desired but also drop `12345`. With `grep -v ^"$$"`, only PIDs that really start with `2345` are dropped. But it occurs to me that PIDs that start like the current one but have extra digits are still dropped. Assuming that's unintended, you can use `grep -v ^"$$"$`. (`$` is the end-of-line anchor. You may want to quote it but--as the OP here observed--you don't have to.) Or take advantage of `-x` and use `grep -vx "$$"` or, as it would no longer need to be treated as a regex, `grep -Fvx "$$"`. – Eliah Kagan Aug 08 '17 at 01:48
-
Ahh three `$` is what I had in the initial version but Serg and another fellow coerced me to take it out and revert to two `$` I'll have to revisit the whole issue next week. It seems like it was simply the right`$` on the wrong side of the tracks `"`. Thanks again for your wonderful insights. – WinEunuuchs2Unix Aug 08 '17 at 01:51
-
@EliahKagan It appears I was wrong [looking back and what Serg and someone else](https://askubuntu.com/questions/848776/how-can-bash-script-kill-sleeping-version-of-itself-already-running/848796#848796) said regarding `"$$"` vs. `"$$$"`. The `"$$$"` solution had broken my script so I reverted back to `"$$"`. I will try out your `"$$"$` suggestion which is probably what they intended to post in the aforementioned link. – WinEunuuchs2Unix Aug 08 '17 at 02:14
-
Do you recall what `^$$$` broke? It *should* work, `"`-quoted or not. (`$$` is just digits so you need only quote it [if `$IFS` contains digits](https://unix.stackexchange.com/a/280935), though I agree with your approach of quoting it for stylistic reasons so it's clear to readers that globbing and word splitting aren't intended.) `^$$$`, `"^$$$"`, `^"$$"$`, or even the confusing `^"$$$"` or `"^$$"$` should all work. But breaking up the leading `$`s, like `^$"$$"`, *doesn't* work right. Anyway I recommend `grep -Fvx "$$"` instead; it's clear and [works well](http://paste.ubuntu.com/25267831/). – Eliah Kagan Aug 08 '17 at 04:34
-
I'm afraid that was in Nov'16 only 3 months after I started bash coding in 'buntu. I'm still only 1 year into this environment and don't know all that much but back then I was truly stumbling around in the dark and grasping at straws. Indeed it may have been a different part of the code causing breakage and I mistakenly mistook it for the `$$$` back then. You are right about cosmetics and I'm guilty of over-quoting "$" strings. "Shell-check" has recently pointed out how $ in front of variables is unnecessary within $(( x+x )) arithmetic expressions and I've started to reduce usage. – WinEunuuchs2Unix Aug 08 '17 at 04:50
-
I will look into `grep -Fvx "$$"` next week in between projects. I must admit I've been focusing on bash built-ins lately and have always been weak on `grep`, `sed`, `tr`, `cut` and `awk`. – WinEunuuchs2Unix Aug 08 '17 at 05:04