bash-лучший способ хранения переменной между прогонами?

Я сделал скрипт 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

переменная является только одним целым числом, поэтому текстовый файл чувствует себя излишним.

5 ответов


нет необходимости использовать var; x будет в области текущей оболочки. Поочередно,

read var < var.txt
# do stuff with var
echo $var > var.txt

Я рекомендую использовать простой текстовый файл для хранения переменной. Однако существует (весьма сомнительный) вариант самоизменяющегося скрипта. ТОЛЬКО ДЛЯ РАЗВЛЕКАТЕЛЬНЫХ ЦЕЛЕЙ!

#!/bin/bash

read val < <( tail -n 1 "" )

(( val++ ))
echo "$val"

tmp=$(mktemp /tmp/XXXXXXX)
sed '$s/.*/'$val'/' "" > "$tmp"
mv "$tmp" ""

exit
0

ключ должен иметь предпоследнюю строку быть командой выхода, поэтому ничего после этого не будет выполняться. Последняя строка-это значение переменной, которое вы хочу упорствовать. Когда скрипт запускается, он reads из собственной последней строки. Перед выходом он использует sed для записи копии самого файла Toa temp, с последней строкой, измененной текущим значением постоянного значения. Затем мы перезаписываем текущий скрипт временным файлом (предполагая, что у нас будет разрешение на это).

а если серьезно? Не делай этого.


Я знаю, это старый вопрос. Но я все же решаю опубликовать свое решение здесь в надежде, что это может быть полезно для других, кто приходит сюда в поисках способа сериализации env vars между сессиями.

простой способ - просто записать " var_name=var_value "в файл, скажем"./окружающая среда." А потом: "источник ./ envrion " на следующих сессиях. Например:

echo "var1=$var1" > ./environ

более полный (и элегантным?) способ сохранения всех атрибутов переменных - использовать "declare-p":

declare -p var1 var2 > ./environ
# NOTE: no '$' before var1, var2

позже, после " source ./envrion " вы можете получить var1 var2 со всеми атрибутами, восстановленными в дополнение к его значению. Это означает, что он может обрабатывать массивы, целые числа и т. д.

одно предостережение для "declare-P xx", хотя: если вы обернете " источник ./environ "в функцию, тогда все исходные переменные видны внутри функции только потому, что" declare " по умолчанию объявляет переменные локальными. Чтобы обойти это, вы можете либо "источник" из любого функция (или в вашей" главной " функции )или измените./ environ добавить "- g " после объявления (что делает соответствующую переменную глобальной). Например:

sed -i 's/^declare\( -g\)*/declare -g/' ./environ
# "\( -g\)?" ensure no duplication of "-g"

1-Вы можете упростить свой скрипт, так как у вас есть только одна переменная

var=`cat var.txt`
# Do some stuff, change var to a new value   
echo $var > var.txt

2 - Вы можете хранить свою переменную в среде:

export var

# Do some stuff, change var to a new value

но вам нужно будет запросить его . script.ksh (точка в начале). Но в нем не должно быть "выхода", и я не уверен, что это сработает в cron...


чтобы сохранить несколько переменных между запусками, решение, которое я рассмотрел, - сохранить их в формате my_var=my_value в отдельном файле.

затем, я включаю две функции для установки и извлечения переменных

  1. в файле хранятся переменные и их значения:

назовем этот файл контексте.dat

# Here I store the variables and their values
my_var_x=1
my_var_y=boo
my_var_z=0
  1. в самом скрипте:

назовем файла multiple_run.sh

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

Это один из подходов, среди других. С помощью такого метода вам нужно создать файл хранения до и создать каждую строку для каждой переменной. Кроме того, контекст.dat априори доступен любому другому скрипту.


в итоге я сделал следующее. Предпочел бы переменные в одном файле, но это немного раздувает код. Как это работает? Вы можете хранить несколько переменных в отдельном файле, например переменные.txt, а затем ваша основная программа в say main.sh - ... Возможно, было бы лучше написать отдельные скрипты для загрузки и сохранения переменных.

для varibles.txt:

A=0
B=0
C=0

для main.sh:

#!/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