Редактировать скрипт оболочки во время его работы - PullRequest
73 голосов
/ 03 августа 2010

Можете ли вы отредактировать скрипт оболочки во время его работы и повлиять ли изменения на работающий скрипт?

Мне любопытно, в каком конкретном случае у меня есть сценарий csh, который запускает множество разных сборок и работает всю ночь. Если что-то случится со мной во время операции, я бы хотел добавить дополнительные команды или закомментировать невыполненные.

Если это невозможно, есть ли оболочка или пакетный механизм, который позволил бы мне сделать это?

Конечно, я попробовал, но пройдет несколько часов, прежде чем я увижу, сработало это или нет, и мне любопытно, что происходит или не происходит за кулисами.

Ответы [ 10 ]

43 голосов
/ 10 июня 2011

[править] См. Также этот ответ, раздел 3 для обходных путей.

Это влияет , по крайней мере, на bash в моей среде, но очень неприятно . Смотрите эти коды. Первый a.sh:

#!/bin/sh

echo "First echo"
read y

echo "$y"

echo "That's all."

b.sh:

#!/bin/sh

echo "First echo"
read y

echo "Inserted"

echo "$y"

# echo "That's all."

У

$ cp a.sh run.sh
$ ./run.sh
$ # open another terminal
$ cp b.sh run.sh  # while 'read' is in effect
$ # Then type "hello."

В моем случае вывод всегда:

hello
hello
That's all.
That's all.

Это непредсказуемо, а значит, опасно. См. этот ответ, раздел 3 для обходных путей.

[добавлено] Точное поведение зависит от одного дополнительного символа новой строки, а также, возможно, также от вашего стиля Unix, файловой системы и т. Д. Если вы просто хотите увидеть некоторые влияния, просто добавьте «echo foo / bar» в b.sh перед и / или после строки «чтение».

33 голосов
/ 17 октября 2013

Попробуйте это ... создайте файл с именем "bash-is-odd.sh":

#!/bin/bash
echo "echo yes i do odd things" >> bash-is-odd.sh

Это показывает, что bash действительно интерпретирует скрипт «по ходу дела». Действительно, редактирование долго выполняемого скрипта имеет непредсказуемые результаты, вставку случайных символов и т. Д. Почему? Поскольку bash читает с позиции последнего байта, редактирование смещает местоположение читаемого текущего символа.

Bash, одним словом, очень, очень небезопасен из-за этой "особенности". svn и rsync при использовании с bash-скриптами особенно беспокоят, потому что по умолчанию они "объединяют" результаты ... редактирование на месте. В rsync есть режим, который это исправляет. svn и git нет.

Я представляю решение. Создайте файл с именем "/ bin / bashx":

#!/bin/bash
source "$1"

Теперь используйте #! / Bin / bashx в своих скриптах и ​​всегда запускайте их с "bashx" вместо bash. Это решает проблему - вы можете безопасно перезаписать ваши скрипты.

Альтернативное (действующее) решение, предложенное / протестированное @ AF7:

{
   # your script
} 
exit $?

Фигурные скобки защищают от изменений, а выход защищает от добавлений. Конечно, нам всем было бы намного лучше, если бы bash поставлялся с опцией, например, '-w' (весь файл) или чем-то, что делало это.

17 голосов
/ 03 августа 2010

Разбейте ваш скрипт на функции, и каждый раз, когда функция вызывается, вы source выводите ее из отдельного файла.Затем вы можете отредактировать файлы в любое время, и ваш скрипт запускает изменения в следующий раз, когда поступит.

foo() {
  source foo.sh
}
foo
2 голосов
/ 06 сентября 2018

Хороший вопрос!Надеюсь, этот простой скрипт поможет

#!/bin/sh
echo "Waiting..."
echo "echo \"Success! Edits to a .sh while it executes do affect the executing script! I added this line to myself during execution\"  " >> ${0}
sleep 5
echo "When I was run, this was the last line"

В linux кажется, что изменения, внесенные в исполняемый файл .sh, выполняются исполняющим скриптом, если вы можете набрать достаточно быстро!

1 голос
/ 09 ноября 2018

Интересное примечание: если вы запускаете скрипт на Python, он не меняется.(Это, вероятно, очевидно для любого, кто понимает, как оболочка выполняет скрипты Python, но подумал, что это может быть полезным напоминанием для тех, кто ищет эту функциональность.)

Я создал:

#!/usr/bin/env python3
import time
print('Starts')
time.sleep(10)
print('Finishes unchanged')

Затем в другой оболочке, пока она спит, отредактируйте последнюю строку.Когда это завершается, он отображает неизмененную строку, предположительно потому, что он запускает .pyc?То же самое происходит в Ubuntu и macOS.

1 голос
/ 03 августа 2010

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

1 голос
/ 03 августа 2010

У меня не установлен csh, но

#!/bin/sh
echo Waiting...
sleep 60
echo Change didn't happen

Запустите это, быстро отредактируйте последнюю строку, чтобы прочитать

echo Change happened

Вывод

Waiting...
/home/dave/tmp/change.sh: 4: Syntax error: Unterminated quoted string

Hrmph.

Я полагаю, что изменения в сценариях оболочки не вступят в силу, пока они не будут перезапущены.

0 голосов
/ 03 августа 2010

Я не слышу ... но как насчет некоторой косвенности:

BatchRunner.sh

Command1.sh
Command2.sh

Command1.sh

runSomething

Command2.sh

runSomethingElse

Тогда вы сможете редактировать содержимое каждого командного файла, прежде чем BatchRunner получит к нему право?

ИЛИ

В более чистой версии BatchRunner будет искать один файл, в котором он будет последовательно выполнять по одной строке за раз.Тогда вы сможете редактировать этот второй файл, пока первый работает правильно?

0 голосов
/ 03 августа 2010

обычно редактирование скрипта редко происходит во время его работы.Все, что вам нужно сделать, это поставить под контроль проверку ваших операций.Используйте операторы if / else для проверки условий.Если что-то не получится, то сделай это, иначе сделай.Это путь.

0 голосов
/ 03 августа 2010

Скрипты не работают таким образом; исполняемая копия не зависит от исходного файла, который вы редактируете. При следующем запуске сценария он будет основан на самой последней сохраненной версии исходного файла.

Возможно, было бы целесообразно разбить этот скрипт на несколько файлов и запускать их по отдельности. Это сократит время выполнения до отказа. (т. е. разделить пакет на один сценарий сборки, каждый из которых выполняется по отдельности, чтобы определить, какой из них вызывает проблему).

...