Могу ли я изменить файл сценария bash (.sh) во время его работы?


28

Предположим, у меня есть скрипт script.sh, выполнение которого занимает некоторое время. Я исполняю это ./script.sh. Пока он работает в окне терминала, я изменяю файл script.sh. Повлияет ли это на уже запущенный процесс?

После его изменения я запускаю измененный файл, поэтому у меня сейчас два запущенных процесса. Это нормально?


Ответы:


36

Когда вы вносите изменения в свой скрипт, вы вносите изменения на диск (жесткий диск - постоянное хранилище); когда вы выполняете скрипт, скрипт загружается в вашу память (RAM).

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

Однако при повторном выполнении измененного сценария без прерывания ранее запущенного экземпляра будет два экземпляра сценария: один с изменениями и старый.

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

Обновление: спасибо зарегистрированному пользователю за указание лучшего ответа на Unix.stackexchange.com.

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

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



@registereduser: о да, этот вопрос только напомнил мне мои уроки ОС. Отредактирую свой ответ, как только я попаду на рабочий стол (прямо сейчас на моем телефоне)
jobin

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

1
Когда я попробовал это с bash v3.2.48 (см. Здесь ), он не буферизовался за пределами конца строки (и сильно потерпел неудачу, когда я изменил скрипт при его выполнении). Я только что протестировал bash v4.3.0, и он буферизовал весь (короткий) скрипт. Так что ... я бы не рассчитывал на какое-то конкретное поведение.
Гордон Дэвиссон

1
@RegisteredUser Не для всех версий bash - см. Пример, на который я ссылался.
Гордон Дэвиссон

4

Я добавлю что-то, что, я думаю, не было сказано в других ответах. Многое зависит только от того, как вы редактируете файл. Думаю, выполнение echo "stuff" >fileиз оболочки (другой экземпляр) действительно перезапишет файл. Но если вы отредактируете файл, например, emacsа затем сохраните, этого не произойдет. Вместо этого редактор переименовывает старый файл в какое-то имя резервной копии (возможно, фактически удаляя предыдущую резервную копию), а затем записывает измененное содержимое буфера в виде нового файла со старым именем (которое теперь является libreated) . Так как оболочка (или другой интерпретатор) читает сценарий почти наверняка открыть файл только один раз, то после этого не зависит от местонахождения файла имя, он просто продолжает читать файл физического диска (идентифицируемый по номеру инода), который был связан с именем файла во время открытия. Таким образом, даже если он читает скрипт в блоках (что было бы самым простым решением при использовании буферизованного текстового ввода-вывода), он продолжал бы читать строки из старого экземпляра файла, который, вероятно, не изменится при вашем редактировании.


+1 Я использую Sublime Text в качестве редактора. Знаете ли вы, если он тоже переименовывает файл, как emacs?
Бекко

1
Я думаю, что большинство редакторов используют схему переименования (даже если они не сохраняют резервные версии), чтобы избежать риска того, что в случае сбоя в процессе записи не останется нетронутой версия текста. Вы можете проверить с помощью "ls -i" (который показывает номера инодов) поведение вашего редактора.
Марк ван Леувен

1

это необходимо обновить, приведенные выше ответы теперь только частично верны:

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

лучший способ сделать это - выполнить следующую последовательность действий: 1) загрузить сценарий в память 2) удалить сценарий с диска 3) записать новый сценарий на диск, сначала удалив версию диска, версия памяти теряет свои ссылки на него так что, когда вы предоставляете новую версию на шаге 3, не будет предпринята попытка bash загрузить новое содержимое в версию памяти.


0

Ответ @ jobin, как правило, правильный, но я добавлю некоторые другие ответы, которые могут быть в зависимости от того, что вы хотите сделать.

Если вы хотите изменить сценарий и хотите знать, что он безопасен, то вы хотите записать в новый файл, а не в существующий. Новый файл может быть расположен там, где был старый. Запишите новую версию в новый файл, а затем используйте ее, mvчтобы переместить на место поверх старой. Файл, который был заменен, все еще существует, он просто не связан с каталогом. Ваш работающий скрипт может продолжать его использовать, и когда этот скрипт закрывает свой дескриптор файла, система знает, что может безопасно очистить файл (как сразу, так и позже).

Если вы хотите вести себя сценарием на лету, у вас есть более сложная проблема. Я ожидаю, что вам нужно встроить его в код скрипта. Сценарии Bash могут обрабатывать сигналы (например, могут отлавливать что-то подобное kill -USR1 [pid]), а затем сценарий может ответить путем перезагрузки некоторого кода. Так что, возможно, вы можете получить функциональность, близкую к тому, что вы хотите, но не зная, что вам нужно, я не вижу веской причины для этого, и я подозреваю, что если вы хотите сделать что-то такое сложное, вы, вероятно, хотите более сложный язык программирования, чтобы сделать это в.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.