Локальные переменные в скрипте Bash должны быть запущены Cron

n.b. большая часть этого ответа имела гораздо больше смысла до редактирования вопроса :)

Ошибка проста:

if [ "$1" == "proto" ]; then
    TESTVAR=
if [ "$1" == "set" ]; then
    HISTFILE=$2
    HISTFILESIZE=$3
elif [ "$1" == "incognito" ]; then
# ....

Второй if здесь должен быть elif. bash жалуется, потому что не может найти подходящий fi.

Есть еще две вещи, которые я хотел бы упомянуть о скрипте:

  1. Он будет запущен в подпрограмме и выполнит вывод команды unset, что не то, что вы хотите:

    $(unset HISTFILE)
    

    Вы должны удалить из него оператор $(...).

  2. Оператор #!/bin/bash подразумевает, что скрипт исполняется отдельно, как аргумент к бинарному файлу /bin/bash. Это не имеет смысла для такого сценария, поэтому я бы не советовал этого делать (и я бы не советовал устанавливать на него разрешение исполняемости).


И последнее. Разбор аргументов с помощью вложенных if/else - немного неудобный способ. Вы можете использовать оператор case:

case $1 in
    (proto) TESTVAR= ;;
    (set)
        HISTFILE=$2
        HISTFILESIZE=$3
        ;;
    #...etc...
    ("")
        # ... put your usage here...
        ;;
    (*)
        echo >&2 "ERROR: Option unrecognized"
        echo >&2
        echo >&2 "run . ./history.bash for help"
        ;;
esac

Заставить скрипт работать под zsh:

  1. Замените использование == на =. Оператор == является нестандартным псевдонимом оператора =, и это один из случаев, когда он ломается.
  2. Переименовать HISTFILESIZE в SAVEHIST
0
28.01.2019, 17:08
2 ответа

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

Во-первых, cronНЕ читает вашу локальную среду, по умолчанию PATH, я полагаю, /usr/bin:/usr/sbin. Один из тестов, который можно попробовать, — это распечатать переменные среды в начале сценария и запустить их в интерактивном режиме, а затем запустить из cron и увидеть разницу.

#!/bin/bash
env

Во-вторых, не думайте, что вы работаете из своего домашнего каталога. Укажите ВСЕ пути. то есть /bin/date, /home/pi/scriptname.sh /home/pi/filenameи т. д.

В-третьих, попробуйте указать в скрипте вашу локальную среду и/или попробуйте добавить опцию -fв ваш shebang

#!/bin/bash
. /home/pi/.bashrc  #Not the period space at the beginning of the line

или

#!/bin/bash -f

В-четвертых, проверьте вывод журнала сценария, чтобы убедиться, что он обрабатывает правильные файлы и действительно устанавливает ваши переменные. Вы можете сделать это, прочитав журнал cron(везде, где у вас установлено значение журнала ), или перенаправить STDIN и STDOUT в файл:

0 1,7,13,19 * * * /home/pi/Dropbox-Uploader/processByDate.sh /home/pi/camfiles.txt 2 >/dev/null 2>&1
0
28.01.2020, 04:03

Проблема в том, что цикл while -реализован в подоболочке. Вот объявление , в котором обсуждается это и возможное правильное решение.

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

#!/bin/bash
c=0
FILE=/tmp/$(basename $0).$$
while IFS= read -r line; do
    ((c++))
    echo "count=$c" > $FILE
done < somefile
. $FILE
echo "Read $count lines"
rm -f $FILE
0
28.01.2020, 04:03

Теги

Похожие вопросы