Может ли скрипт оболочки указать, что его строки изначально загружены в память? - PullRequest
9 голосов
/ 25 февраля 2010

ОБНОВЛЕНИЕ: это репост Как сделать скрипты оболочки устойчивыми к изменению источника при их запуске

Это то, что беспокоит меня время от времени:

  1. Я пишу сценарий оболочки (bash) для быстрой и грязной работы
  2. Я запускаю скрипт, и он довольно долго запускается
  3. Пока он работает, я редактирую несколько строк в скрипте, настраивая его для другой работы
  4. Но первый процесс все еще читает тот же файл скрипта и все испортил.

Видимо, скрипт интерпретируется путем загрузки каждой строки из файла по мере необходимости . Есть ли способ, чтобы скрипт мог указать оболочке, что весь файл скрипта должен быть одновременно считан в память? Например, Perl-скрипты, кажется, делают это: редактирование файла кода не влияет на процесс, который его сейчас интерпретирует (потому что он изначально анализируется / компилируется?).

Я понимаю, что есть много способов обойти эту проблему. Например, я мог бы попробовать что-то вроде:

cat script.sh | sh

или

sh -c "`cat script.sh`"

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

Так что я надеялся на самое простое решение, которое включало бы модификации только в сценарий, а не в способ его вызова. Могу ли я просто добавить одну или две строки в начале скрипта? Я не знаю, существует ли такое решение, но я предполагаю, что оно может использовать переменную $ 0 ...

Ответы [ 6 ]

8 голосов
/ 01 марта 2010

Лучший ответ, который я нашел, - это очень небольшая вариация решений, предлагаемых для Как сделать скрипты оболочки более устойчивыми к изменению источника при их запуске . Спасибо Camh за то, что отметили репост!

#!/bin/sh
{
    # Your stuff goes here
    exit
}

Это гарантирует, что весь ваш код будет проанализирован изначально; обратите внимание, что «выход» имеет решающее значение для обеспечения того, чтобы файл не был доступен позже, чтобы увидеть, есть ли дополнительные строки для интерпретации. Кроме того, как отмечалось в предыдущем посте, это не гарантирует безопасности других скриптов, вызываемых вашим скриптом.

Спасибо всем за помощь!

2 голосов
/ 25 февраля 2010

Используйте редактор, который не изменяет существующий файл, а вместо этого создает новый файл, а затем заменяет старый файл. Например, используя :set writebackup backupcopy=no в Vim.

2 голосов
/ 25 февраля 2010

Как насчет решения о том, как вы его редактируете.

Если скрипт запущен, перед его редактированием сделайте следующее:

mv script script-old
cp script-old script
rm script-old

Поскольку оболочка сохраняет файл открытым, пока вы не измените содержимое открытого inode, все будет работать нормально.

Вышеописанное работает, потому что mv сохранит старый inode, а cp создаст новый. Поскольку содержимое файла на самом деле не будет удалено, если он открыт, вы можете удалить его сразу же, и он будет очищен, как только оболочка закроет файл.

1 голос
/ 26 февраля 2010

Согласно документации bash, если вместо

#!/bin/bash
body of script

Вы пытаетесь

#!/bin/bash
script=$(cat <<'SETVAR'
body of script
SETVAR)
eval "$script"

тогда я думаю, что вы будете в бизнесе.

0 голосов
/ 26 февраля 2010

Если вы используете Emacs, попробуйте M-x customize-variable break-hardlink-on-save. Установка этой переменной скажет Emacs записать временный файл, а затем переименовать временный файл поверх оригинала, а не редактировать исходный файл напрямую. Это должно позволить запущенному экземпляру сохранить его неизмененную версию, пока вы сохраняете новую версию.

Предположительно, другие полуинтеллектуальные редакторы будут иметь аналогичные опции.

0 голосов
/ 25 февраля 2010

Подумайте о создании нового пути для быстрой и грязной работы. Если вы начинаете свои сценарии с: #!/usr/local/fastbash

или что-то еще, тогда вы можете написать упаковщик fastbash, который использует один из упомянутых вами методов. Для переносимости можно просто создать символическую ссылку с fastbash на bash или оставить комментарий в сценарии, в котором говорится, что можно заменить fastbash на bash.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...