ОБНОВЛЕНИЕ: это - пересообщение того, Как сделать сценарии оболочки устойчивыми к источнику изменяемый, когда они работают
Это - немного вещи, которая беспокоит меня время от времени:
По-видимому, сценарий интерпретируется путем загрузки каждой строки из файла, поскольку это необходимо. Есть ли некоторый способ, которым у меня может быть сценарий, указывают к оболочке, что весь файл сценария должен быть считан в память внезапно? Например, сценарии Perl, кажется, делают это: редактирование файла кода не влияет на процесс, это в настоящее время интерпретирует его (потому что это первоначально анализируется/компилируется?).
Я понимаю, что существует много способов, которыми я мог обойти эту проблему. Например, я мог попробовать что-то как:
cat script.sh | sh
или
sh -c "`cat script.sh`"
... хотя они не могли бы работать правильно, если файл сценария является большим и существуют пределы на размер потоковых буферов и параметров командной строки. Я мог также записать вспомогательную обертку, которая копирует файл сценария в заблокированный временный файл и затем выполняет его, но это не кажется очень портативным.
Таким образом, я надеялся на простое решение, которое включит модификации только к сценарию, не пути, которым это вызывается. Я могу просто добавить строку или два в начале сценария? Я не знаю, существует ли такое решение, но я предполагаю, что оно могло бы использовать переменную за 0$...
Лучший ответ, который я нашел, - это очень небольшая вариация решения, предложенного в Как сделать сценарии оболочки устойчивыми к изменению исходного кода в процессе их выполнения. Спасибо camh за заметку о перепосте!
#!/bin/sh
{
# Your stuff goes here
exit
}
Это гарантирует, что весь ваш код будет разобран изначально; обратите внимание, что 'exit' критически важен для обеспечения того, чтобы файл не был доступен позже, чтобы посмотреть, есть ли дополнительные строки для интерпретации. Также, как отмечено в предыдущем сообщении, это не является гарантией того, что другие скрипты, вызываемые вашим скриптом, будут в безопасности.
Спасибо всем за помощь!
Если вы используете Emacs, попробуйте M-x customize-variable break-hardlink-on-save
. Установка этой переменной скажет Emacs записать во временный файл и затем переименовать временный файл поверх оригинала вместо непосредственного редактирования исходного файла. Это должно позволить работающему экземпляру сохранить свою неизмененную версию, пока вы сохраняете новую версию.
Предположительно, у других полуинтеллектуальных редакторов были бы аналогичные возможности.
Подумайте о том, чтобы создать новую дорогу для вашей быстрой и грязной работы. Если вы начинаете свои скрипты с:
#! / Usr / local / fastbash
или что-то в этом роде, то вы можете написать оболочку fastbash, которая использует один из упомянутых вами методов. Для переносимости можно просто создать символическую ссылку с fastbash на bash или оставить комментарий в скрипте, в котором говорится, что можно заменить fastbash на bash.
Как насчет решения того, как вы его редактируете.
Если сценарий запущен, перед его редактированием сделайте следующее:
mv script script-old
cp script-old script
rm script-old
Поскольку оболочка сохраняет файл открытым до тех пор, пока вы не изменяете содержимое открытого индексного дескриптора, все будет работать нормально.
Вышеупомянутое работает, потому что mv сохранит старый индексный дескриптор, а cp создаст новый. Поскольку содержимое файла не будет фактически удалено при его открытии, вы можете удалить его сразу, и он будет очищен, как только оболочка закроет файл.
Используйте редактор, который не изменяет существующий файл, а создает новый файл, а затем заменяет старый. Например, используя :set writebackup backupcopy=no
в Vim.
Согласно документации bash, если вместо
#!/bin/bash
body of script
вы попробуете
#!/bin/bash
script=$(cat <<'SETVAR'
body of script
SETVAR)
eval "$script"
то, я думаю, вы будете в деле.