Подтвердить что ты не робот

Не удалось заменить bash script на новую версию, чтобы запустить исполняемый экземпляр script

Я запускаю скрипты bash из java-программ на сервере. Я просто загрузил новую версию script, намеревающуюся на следующий запуск script, чтобы использовать эту версию. Я не хотел прерывать существующие, запущенные экземпляры script. Тем не менее, я только что получил более 100 уведомлений об авариях с моих 300 серверов. Я предполагаю, что замена рабочего bash script на новую версию вызвала это. Однако для этого требуется, чтобы выполняемый bash script читал с диска, когда он попадает на каждый новый шаг. Это как это работает?

В работающих версиях bash script выполняется некоторое программное обеспечение трассировки лучей. Каждый прогон занимает 2 часа. Подэтапы занимают от 5 минут до 1,5 часов. script всегда сообщает о сбое после завершения шага в script. Он никогда не сообщает о сбое уже запущенного подшага. В некоторых авариях сообщается о том, что не найдено команд, которые я не могу найти в script. Различные аварии сообщают о разных местах.

помощь!

EDIT: я скопировал script на все 300 серверов с помощью scp. Файл был заменен файловой системой. Это не общий файл.

4b9b3361

Ответ 1

SiegeX имеет половину права - bash загрузит в память весь script, поэтому script может продолжать работать, даже если исходный файл будет удален во время процесса. Но bash также проверяет, обновляется ли исходный файл, пока работает script. Если он был, bash перезагрузит его и продолжит его запуск из текущей позиции, откройте файл, найдите текущую позицию script и продолжите запуск script из этого точка.

Здесь доказательство понятия script:

# If you modify a script, will it change the behavior of
# processes that are currently running that script?
# Does this script print "Foo" or "Bar"?

cat >foo.sh <<EOF
sleep 5
echo Foo
EOF

bash foo.sh &
sleep 2

cat >foo.sh <<EOF
sleep 5
echo Bar
EOF

wait

Таким образом, результат не изменяет исходные файлы сценариев bash, если вы беспокоитесь о процессах, которые в настоящее время работают, script.


(Этот script, однако, отображает "Foo". "Текущее положение" bash script всегда находится в начале или конце строки.)

echo "sleep 5 ; echo Foo" > foo.sh
bash foo.sh &
sleep 2
echo "sleep 5 ; echo Bar" > foo.sh
wait

Ответ 2

Не обновляйте запущенную систему, если вы можете ее избежать


Удаление script - это одно, но его изменение может привести к более "интересным" результатам.

Кроме того, изменение файла, который реплицируется и/или подключен к сети, вводит поведение, специфичное для протоколов файловой системы и развертывания. Они не будут точно смоделированы с помощью простого теста на локальном жестком диске или в том случае, когда сетевое крепление изменено в той же системе, которая читает файл.

Кроме того, "загрузка" этого файла на 300 серверов знаменует все виды замечательной сложности, которые, по-видимому, у нас, переполняющих, недостаточно информации для анализа.

ISTM, что ваши проблемы, вероятно, связаны с обновлением. Я думаю, что команды тайны могут поступать из bash части, содержащей часть script из старой версии и части из новой версии. Я знаю, что вы должны, вероятно, закрыть подсистему, если это возможно, при обновлении.

Ответ 3

Я не уверен, что все изменилось с момента ответа mob, который был принят, но в bash 4.3.46 (например, поставляется с ubuntu 16.04), правда, bash отслеживает script файл для изменений, но это не работает, если файл удален.

Итак, небольшая модификация его script делает "правильную" вещь:

# If you modify a script, will it change the behavior of
# processes that are currently running that script?
# Does this script print "Foo" or "Bar"?

cat >foo.sh <<EOF
sleep 5
echo Foo
EOF

bash foo.sh &
sleep 2

rm foo.sh

cat >foo.sh <<EOF
sleep 5
echo Bar
EOF

wait

Теперь он печатает Foo.

Ответ 4

После вызова bash отменит новый процесс и загрузит script в память. Если только script не ссылается, он все равно должен работать. Ниже приведен пример script, удаляющий себя с диска и продолжающий работу, пока он не попытается получить доступ через $0

Ввод

#!/bin/bash

echo "I can't take it anymore"
echo "Goodbye World!"

rm -f "$0"

echo "Wait, I change my mind!"

sed 's/Goodbye/Hello/' "$0"

Выход

$ ./suicide.sh
I can't take it anymore
Goodbye World!
Wait, I change my mind!
sed: can't read ./suicide.sh: No such file or directory