Информация текущего времени не хранится в файле, скорее она синхронизируется от Ваших аппаратных часов с /sbin/hwclock
во время начальной загрузки. Видя эту дату, обычно средства, Ваши системные часы были сброшены, это часто вызывается неисправной батареей на Вашей системной плате (батарея CMOS),
Дата 31 декабря 1969 является опорной датой (представляющий это число в битах, это было бы всеми нулями), когда Ваша система сбрасывает системные часы, это сбрасывается к опорной дате (все нули).
Как устранить проблему
date
(направления находятся в man date
)hwclock --systohc
И Вы вернулись в бизнесе. Для непрерывной синхронизации часов с внешним источником необходимо посмотреть на ntp
.
Если требуется протестировать батарею CMOS, самый простой способ сделать так состоит в том, чтобы завершить работу системы, удалить шнур питания, ожидать в течение приблизительно 5 минут (чтобы удалить резервную мощность и позволить конденсаторам высушить), затем запуститься, все создает резервную копию. Если Ваши часы сбросили снова, получите новую батарею. Можно обычно находить корректную батарею в аптеке. Если это - сервер, необходимо связаться поставщиком для замены (как можно скорее).
Я не знаю ни о каком механизме в рамках Linux, который позволил бы Вам контролировать состояние своей батареи CMOS.
В Unix большинство редакторов работает путем создания нового временного файла, содержащего отредактированное содержание. Когда отредактированный файл сохранен, исходный файл удален, и временный файл переименован к настоящему имени. (Существуют, конечно, различные гарантии для предотвращения dataloss.) Это - например, стиль, используемый sed
или perl
при вызове с -i
("оперативный") флаг, который не является действительно "оперативным" вообще. Это нужно было назвать "новым местом со старым названием".
Это работает хорошо, потому что Unix гарантирует (по крайней мере, для локальных файловых систем), что открытый файл продолжает существовать, пока он не закрывается, даже если он "удален", и создается новый файл с тем же именем. (Не случайно, что системный вызов Unix для "удаления" файла на самом деле называют, "удаляют связь".) Так, вообще говоря, если интерпретатор оболочки имеет некоторый открытый исходный файл, и Вы "редактируете" файл, таким образом описанный выше, оболочка не будет даже видеть изменений, так как это все еще имеет исходный открытый файл.
[Примечание: как со всеми основанными на стандартах комментариями, вышеупомянутое подвергается нескольким интерпретациям и существуют различные угловые случаи, такие как NFS. Педанты могут заполнить комментарии за исключениями.]
Конечно, возможно изменить файлы непосредственно; это просто не очень удобно для редактирования целей, потому что, в то время как можно перезаписать данные в файле, Вы не можете удалить или вставить, не смещая весь после данных, которые подразумевали бы довольно большую перезапись. Кроме того, при выполнении того смещения содержание файла будет непредсказуемо и процессы, которые имели открытый файл, пострадает. Для схождения с рук этого (как с системами баз данных, например), Вам нужен сложный набор протоколов модификации и распределенных блокировок; материал, который является далеко за пределами объема типичной утилиты редактирования файла.
Так, если Вы хотите отредактировать файл, в то время как то, что это было обработанным оболочкой, у Вас есть две опции:
Можно добавить в файл. Это должно всегда работать.
Можно перезаписать файл с новым содержанием точно той же длины. Это может или не может работать, в зависимости от того, считала ли оболочка уже ту часть файла или нет. Так как большая часть файлового ввода-вывода включает буферы чтения, и так как все оболочки, которые я знаю, читают всю составную команду прежде, чем выполнить его, довольно маловероятно, что можно сойти с рук это. Это, конечно, не было бы надежно.
Я не знаю ни о какой формулировке в стандарте Posix, который на самом деле требует возможности добавления в файл сценария, в то время как файл выполняется, таким образом, это не могло бы работать с каждым Posix совместимая оболочка, а тем более с текущим предложением почти - и оболочки sometimes-posix-compliant. Так YMMV. Но насколько я знаю, это действительно работает надежно с ударом.
Как доказательство, вот реализация "без циклов" печально известных 99 бутылок программы пива в ударе, который использует dd
перезаписывать и добавлять (перезапись, по-видимому, безопасна, потому что она заменяет в настоящее время строкой выполнения, которая всегда является последней строкой файла с комментарием точно той же длины; я сделал это так, чтобы конечный результат мог быть выполнен без поведения самоизменения.)
#!/bin/bash
if [[ $1 == reset ]]; then
printf "%s\n%-16s#\n" '####' 'next ${1:-99}' |
dd if=/dev/stdin of=$0 seek=$(grep -bom1 ^#### $0 | cut -f1 -d:) bs=1 2>/dev/null
exit
fi
step() {
s=s
one=one
case $beer in
2) beer=1; unset s;;
1) beer="No more"; one=it;;
"No more") beer=99; return 1;;
*) ((--beer));;
esac
}
next() {
step ${beer:=$(($1+1))}
refrain |
dd if=/dev/stdin of=$0 seek=$(grep -bom1 ^next\ $0 | cut -f1 -d:) bs=1 conv=notrunc 2>/dev/null
}
refrain() {
printf "%-17s\n" "# $beer bottles"
echo echo ${beer:-No more} bottle$s of beer on the wall, ${beer:-No more} bottle$s of beer.
if step; then
echo echo Take $one down, pass it around, $beer bottle$s of beer on the wall.
echo echo
echo next abcdefghijkl
else
echo echo Go to the store, buy some more, $beer bottle$s of beer on the wall.
fi
}
####
next ${1:-99} #
bash
идет длинным путем, чтобы удостовериться, что он читает команды прежде, чем выполнить их.
Например, в:
cmd1
cmd2
Оболочка будет читать сценарий блоками, так вероятно, чтение обе команды, интерпретировать первую и затем искать назад в конец cmd1
в сценарии и читают сценарий снова для чтения cmd2
и выполните его.
Можно легко проверить его:
$ cat a
echo foo | dd 2> /dev/null bs=1 seek=50 of=a
echo bar
$ bash a
foo
(хотя смотря на strace
вывод на этом, кажется, что это делает некоторые более необычные вещи (как считанный данные несколько раз, ищите назад...) чем тогда, когда я попробовал те же несколько лет назад, таким образом, мой оператор выше о lseeking назад не может больше применяться на более новые версии).
Если однако Вы пишете свой сценарий как:
{
cmd1
cmd2
exit
}
Оболочка должна будет читать до закрытия }
, хранилище, что в памяти и выполняют его. Из-за exit
, оболочка не будет читать из сценария снова, таким образом, можно будет отредактировать его безопасно, в то время как оболочка интерпретирует его.
С другой стороны, при редактировании сценария, удостоверьтесь, что Вы пишете новую копию сценария. Оболочка будет продолжать читать исходную (даже если это будет удалено или переименовано).
Чтобы сделать это, переименовать the-script
кому: the-script.old
и копия the-script.old
кому: the-script
и отредактируйте его.
Нет действительно никакого безопасного способа изменить сценарий, в то время как он работает, потому что оболочка может использовать буферизацию для чтения файла. Кроме того, если сценарий будет изменен путем замены его с новым файлом, то оболочки обычно только считают новый файл после выполнения определенных операций.
Часто, когда сценарий изменяется при выполнении, оболочка заканчивает тем, что сообщила о синтаксических ошибках. Это - то, вследствие того, что, когда оболочка закрывает и вновь открыла файл сценария, она использует байтовое смещение в файл, чтобы изменить местоположение себя по возврату.
Вы могли обойти это путем поставления капкана на сценарии и затем использования exec
взять новое содержание сценария. Отметьте однако, exec
звоните запускает сценарий с нуля а не от того, где он достиг в рабочем процессе, и таким образом, сценарий B назовут (на поэтому дальше).
#! /bin/bash
CMD="$0"
ARGS=("$@")
trap reexec 1
reexec() {
exec "$CMD" "${ARGS[@]}"
}
while : ; do sleep 1 ; clear ; date ; done
Это продолжит отображать дату на экране. Я мог затем отредактировать свой сценарий и изменение date
кому: echo "Date: $(date)"
. При записи, что под управлением сценарий все еще просто отображает дату. Как когда-либо, если я отправляю сигнал, что я установил trap
для получения сценарий будет exec
(заменяет текущий рабочий процесс указанной командой), который является командой $CMD
и аргументы $@
. Можно сделать это путем издания kill -1 PID
- где PID является PID под управлением сценария - и вывод изменяется на шоу Date:
перед date
команда производится.
Вы могли сохранить "состояние" своего сценария во внешнем файле (в, говорят, что/tmp), и читают содержание для знания, где "возобновиться" на, когда программа является re-exec'ed. Вы могли затем добавить дополнительное завершение прерываний (SIGINT/SIGQUIT/SIGKILL/SIGTERM) для разрешения этого tmp файл поэтому, когда Вы перезапустите после прерывания "Сценария A", это запустится с начала. Версия с сохранением информации была бы чем-то как:
#! /bin/bash
trap reexec 1
trap cleanup 2 3 9 15
CMD="$0"
ARGS=("$@")
statefile='/tmp/scriptA.state'
EXIT=1
reexec() { echo "Restarting..." ; exec "$CMD" "${ARGS[@]}"; }
cleanup() { rm -f $statefile; exit $EXIT; }
run_scriptB() { /path/to/scriptB; echo "scriptC" > $statefile; }
run_scriptC() { /path/to/scriptC; echo "stop" > $statefile; }
while [ "$state" != "stop" ] ; do
if [ -f "$statefile" ] ; then
state="$(cat "$statefile")"
else
state='starting'
fi
case "$state" in
starting)
run_scriptB
;;
scriptC)
run_scriptC
;;
esac
done
EXIT=0
cleanup
$0
и $@
в начале сценария и использующий те переменные в exec
вместо этого.
– Drav Sloan
29.08.2013, 03:46
export beer=100
прежде, чем запустить скрипт, это работает как ожидалось. – Daniel Hershcovich 04.09.2013, 10:10