Замена скрипта оболочки? - PullRequest
1 голос
/ 15 июня 2011

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

  • Для каждой команды, если я не проверю явно коды возврата, сценарий может завершиться с кодом завершения 0, даже если я этого не хочу. поэтому за каждой командой оболочки следует оператор if, чтобы увидеть, правильно ли завершилась программа или нет ..
  • Передача переменных и создание надежного синтаксического анализатора аргументов командной строки трудны (что-то вроде optparse в Python).
  • Очень сложно отлаживать.

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

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

Ответы [ 5 ]

2 голосов
/ 15 июня 2011

Вы смотрели на использование рубина. В нем есть несколько кусочков синтаксического сахара, которые упрощают написание сценариев типа оболочки. В частности, строки с обратными галочками работают так же, как и %x{..}. На самом деле существует пять способов запустить внешнюю команду в ruby.

2 голосов
/ 15 июня 2011

Задумывались ли вы об использовании "set -e", если можете зависеть от состояния выхода программ, которые вы запускаете?

1 голос
/ 18 июня 2011

Это похоже на субъективный открытый вопрос, но я добавлю два своих цента.

Обработка ошибок

set -e ненадежно; различные реализации по-разному интерпретируют определение POSIX -e.

Вот что я делаю, чтобы ловить ошибки:

log() { printf '%s\n' "$*"; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$*"; exit 1; }
try() { "$@" || fatal "command '$@' failed"; }

try echo "before the false"
try false
try echo "after the false"

выходы:

before the false
ERROR: command 'false' failed

Анализ аргумента

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

1 голос
/ 15 июня 2011

Все хорошие предложения, приведенные выше, особенно set -e, которые были бы хорошим базовым решением для вашего возражения № 1.

Другой подход к отлову ошибок подпроцесса оболочки заключается в том, чтобы использовать оператор if, т.е.

if true ; then
    printf "success\n"
else
    printf "failure\n"
fi

будет самой базовой иллюстрацией этой идеи.

Редактировать

Вот более сложный пример, модифицированный из другой публикации здесьна SO

if ls /path/to/files*  /dev/null 2>&1 ; then
    echo "files do exist"
else
    echo "files do not exist"
fi

Наконец, возможно встроить полные команды конвейера с синтаксисом if cmd ; then, но последний вызов в конвейере - это то, что возвращает истину или ложность всего конвейера.

конец редактирования

К сожалению, некоторые утилиты Unix не подходят (для этой цели) с их кодами возврата, но это очень зависит от платформы (может быть, ядумаю о Sun4 sed, и определенно много ftp клиентов).Возможно, в хорошем дистрибутиве Linux такой проблемы нет, но вам нужно проверять (и, возможно, документировать) каждую утилиту, когда вы начинаете ее использовать.

Для возражения № 2, разбора аргументов, я могу предложить полный шаг в этом вопросе, с отрицательным кодом, который поначалу может быть сложно понять другим.

Вместо того, чтобы полагатьсяЦикл while с getargs и инструкциями case для обработки аргументов: посмотрите, поможет ли вам добавление переменных окружения к вызову подпроцесса, т. е.

код с флагами

 cat myProgram.sh
 #! /bin/bash
 set -e
 if ${testingMode:-false} ; then
     printf "${0##*/}:TestingMode:Starting:args=${@}"
 fi

 # more code

Теперь, а неимея встроенную внутреннюю обработку для обработки testMode, вы предварительно ожидаете переменную в командной строке скрипта и временно «включаете» ее, т. е. ::

 testingMode=true ./myProgram.sh otherargs that makes sense as args

вы можете иметь столько префиксированных переменныхв начале команды, как вам нравится, поэтому возможно создать сценарий, который не имеет никакой обработки аргументов.Иногда это имеет смысл, а иногда нет.(Между прочим, я получил эту технику, прочитав «Среду программирования Unix» Кернигана и Пайка)

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

Ваше последнее возражение «трудно отладить» защищать труднее, особенно ошибки, связанные с несовпадающими {}, (), "и". Существует множество отладчиков ksh, которые работают по принципу ранних версий.Отладчики языка c, dbx и gdbx.

Удачи. Сообщите нам, когда найдете язык программирования, который может «делать то, что я имею в виду»: -) !!

Я надеюсьэто помогает.

1 голос
/ 15 июня 2011

В чем вопрос? Я не думаю, что многие считают Python «многословным». Он часто упоминается, чтобы показать, что язык НЕ может быть многословным по сравнению, скажем, с Java.

Кстати, Perl, синтаксически и исторически, может быть помещен между сценариями оболочки и Python, я думаю.

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