bash——在运行之间存储变量的更好方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12334495/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
bash—Better way to store variable between runs?
提问by shardbearer
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.
我制作了一个 bash 脚本,我每小时使用 crontab 运行该脚本,我需要存储一个变量,以便下次运行时可以访问它。脚本每次运行时都会更改变量,因此我无法对其进行硬编码。现在我正在将其写入 txt 文件,然后再将其读回。还有比这更好的方法吗?我阅读 txt 文件的方式是我在这里找到的,我不明白,而且有点笨拙。没有内置命令吗?无论如何,这是适用的代码,其中一些变量已更改以使其更易于阅读。
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.
变量只是一个整数,所以文本文件感觉有点大材小用。
采纳答案by chepner
There's no need to use var; xwill be in scope for the current shell. Alternately,
没有必要使用var; x将在当前 shell 的范围内。交替,
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 "echo "var1=$var1" > ./environ
" )
(( val++ ))
echo "$val"
tmp=$(mktemp /tmp/XXXXXXX)
sed '$s/.*/'$val'/' "declare -p var1 var2 > ./environ
# NOTE: no '$' before var1, var2
" > "$tmp"
mv "$tmp" "sed -i 's/^declare\( -g\)*/declare -g/' ./environ
# "\( -g\)?" ensure no duplication of "-g"
"
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 reads from its own last line. Before it exits, it uses sedto 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).
关键是让倒数第二行是退出命令,所以它之后什么都不会执行。最后一行是你想要持久化的变量值。当脚本运行时,它read从它自己的最后一行开始。在退出之前,它使用sed将自身的副本写入临时文件,并使用持久值的当前值修改最后一行。然后我们用临时文件覆盖当前脚本(假设我们有权限这样做)。
But seriously? Don't do this.
不过实话说?不要这样做。
回答by Lungang Fang
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:
简单的方法是将“var_name=var_value”写入文件,比如“./environ”。然后在以下会话中“source ./envrion”。例如:
var=`cat var.txt`
# Do some stuff, change var to a new value
echo $var > var.txt
A more comprehensive (and elegant?) way which persist all attributes of variables is to make use of "declare -p":
保留变量所有属性的更全面(更优雅?)的方法是使用“declare -p”:
export var
# Do some stuff, change var to a new value
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.
稍后,在“source ./envrion”之后,您可以获得 var1 var2,除了其值之外还恢复了所有属性。这意味着它可以处理数组、整数等。
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:
但是,对“declare -p xx”的一个警告:如果将“source ./environ”包装到一个函数中,那么所有源变量在函数中都是可见的,因为默认情况下“declare”将变量声明为本地变量。为了避免这种情况,您可以从任何函数(或在您的“主”函数中)“源”或修改 ./environ 以在声明后添加“-g”(这使相应的变量成为全局变量)。例如:
# Here I store the variables and their values
my_var_x=1
my_var_y=boo
my_var_z=0
回答by Majid Laissi
1- You can simplify your script, as you only have one variable
1- 您可以简化脚本,因为您只有一个变量
context=./context.dat
function update_variables(){
# update the variable context
source $context
}
function set_variable(){
# store variable
variable= #variable to be set
value= # value to give to the value
# modify the file storing the value
sed -i 's/'${variable}'.*/'${variable}'='${value}'/' $context
}
##################
# Test code
echo var_x
update_variables
echo var_x
# do something
set_variable var_x 2
echo $var_x
2- You can store your variable in the environment:
2-您可以将变量存储在环境中:
A=0
B=0
C=0
But you'll need to prompt it . script.ksh(dot at the beggining). But it shouldn't have 'exit' in it and i'm not sure this would work in cron...
但是你需要提示它. script.ksh(在开始处加点)。但它不应该有“退出”,我不确定这是否适用于 cron ......
回答by Uncle Ben Ben
To store multiple variables between runs, a solution I considered is to save them under the format my_var=my_valuein a separated file.
为了在运行之间存储多个变量,我考虑的一个解决方案是将它们以格式保存my_var=my_value在一个单独的文件中。
Then, I include two function to set and retrieve the variables
然后,我包含两个函数来设置和检索变量
- In the file storing the variables and their values:
- 在存储变量及其值的文件中:
Let's call this file context.dat
让我们称这个文件为context.dat
#!/bin/bash
#reload variables
A=`cat ./variables.txt|grep "A="|cut -d"=" -f2`
B=`cat ./variables.txt|grep "B="|cut -d"=" -f2`
C=`cat ./variables.txt|grep "C="|cut -d"=" -f2`
#print variables
printf "$A\n"
printf "$B\n"
printf "$C\n"
#update variables
A=$((($A+1)))
B=$((($B+2)))
C=$((($C+3)))
#save variables to file
#for A
#remove entry for A
cat ./variables.txt|grep -v "A=">>./tmp.txt
#save entry for A
printf "A=$A\n">>./tmp.txt
#move tmp.txt to variables.txt
mv ./tmp.txt ./variables.txt
#for B
#remove entry for B
cat ./variables.txt|grep -v "B=">>./tmp.txt
#save entry for B
printf "B=$B\n">>./tmp.txt
#move tmp.txt to variables.txt
mv ./tmp.txt ./variables.txt
#for C
#remove entry for C
cat ./variables.txt|grep -v "C=">>./tmp.txt
#save entry for C
printf "C=$C\n">>./tmp.txt
#move tmp.txt to variables.txt
mv ./tmp.txt ./variables.txt
- In the actual script:
- 在实际脚本中:
Let's call the file multiple_run.sh
让我们调用文件multiple_run.sh
##代码##This is one approach among other. With such method, you need to create the storing file before and create each line for each variable. Besides, the context.dat is a priori accessible by any other script.
这是一种方法。使用这种方法,您需要先创建存储文件,并为每个变量创建每一行。此外,context.dat 是任何其他脚本都可以先验访问的。
回答by ockert
I ended up doing the following. Would prefer the variables in one file, but this bloats the code slightly. How does this read thing work? You can store multiple variables in a seperate file, say variables.txt, and then have your main program in say main.sh. It might be better to write seperate scripts for loading and saving variables though.
我最终做了以下事情。更喜欢一个文件中的变量,但这会使代码稍微膨胀。这个阅读器是如何工作的?您可以将多个变量存储在一个单独的文件中,比如 variables.txt,然后将您的主程序放在 main.sh 中。不过,最好编写单独的脚本来加载和保存变量。
For varibles.txt:
对于变量.txt:
##代码##For main.sh:
对于 main.sh:
##代码##
