I've made a bash script which I run every hour with crontab, and I need to store one variable so that I can access it the next time I run it. The script changes the variable every time it runs, so I can't hardcode it in. Right now I am writing it to a txt file and then reading it back. Is there a better way to do it than this? And the way I am reading the txt file is something I found on here, I don't understand it, and it's kinda clunky. Is there not a built in command for this? Anyway, here's the applicable code, with some of the variables changed to make it easier to read.
while read x; do var=$x done < var.txt # Do some stuff, change var to a new value echo $var > var.txt
The variable is only a single integer, so the text file feels overkill.
General rule: quote it if it can either be empty or contain spaces (or any whitespace really) or special characters (wildcards). Not quoting strings with spaces often leads to the shell breaking apart a single argument into many.
From man bash : -s If the -s option is present, or if no arguments remain after option processing, then commands are read from the standard input. This option allows the positional parameters to be set when invoking an interactive shell.
To store the output of a command in a variable, you can use the shell command substitution feature in the forms below: variable_name=$(command) variable_name=$(command [option ...] arg1 arg2 ...) OR variable_name='command' variable_name='command [option ...]
There's no need to use var
; x
will be in scope for the current shell. Alternately,
read var < var.txt # do stuff with var echo $var > var.txt
I recommend using a simple text file to store the variable. However, there is the (highly questionable) option of a self-modifying script. FOR ENTERTAINMENT PURPOSES ONLY!
#!/bin/bash read val < <( tail -n 1 "$0" ) (( val++ )) echo "$val" tmp=$(mktemp /tmp/XXXXXXX) sed '$s/.*/'$val'/' "$0" > "$tmp" mv "$tmp" "$0" exit 0
The key is to have the next-to-last line be the exit command, so nothing after it will execute. The last line is the variable value you want to persist. When the script runs, it read
s from its own last line. Before it exits, it uses sed
to write a copy of itself toa temp file, with the last line modified with the current value of the persistent value. Then we overwrite the current script with the temp file (assuming we will have permission to do so).
But seriously? Don't do this.
I know this is an old question. But, I still decide to post my solution here in the hope that it might be helpful to others who come here in search of a way to serialize env vars between sessions.
The simple way is just write "var_name=var_value" into a file, say "./environ". And then "source ./envrion" in following sessions. For example:
echo "var1=$var1" > ./environ
A more comprehensive (and elegant?) way which persist all attributes of variables is to make use of "declare -p":
declare -p var1 var2 > ./environ # NOTE: no '$' before var1, var2
Later on, after "source ./envrion" you can get var1 var2 with all attributes restored in addition to its value. This means it can handle arrays, integers etc.
One caveat for the "declare -p xx", though: if you wrap the "source ./environ" into a function, then all sourced variables are visible within the function only because "declare" by default declares variables as local ones. To circumvent this, you may either "source" out of any function (or in your "main" function) or modify the ./environ to add "-g" after declare (which makes corresponding variable global). For instance:
sed -i 's/^declare\( -g\)*/declare -g/' ./environ # "\( -g\)?" ensure no duplication of "-g"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With