Bash скрипт и аномалия cron - PullRequest
1 голос
/ 14 декабря 2009

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

Обычно скрипт (ниже) получает PID моей программы и получает дату / время его создания из записи в каталоге / proc /. Затем он получает текущую дату / время из системы и преобразует эти два значения в секунды с 1970 года с помощью команды «дата», прежде чем окончательно вычесть их. Это обычно заканчивается 2100 секундами или чем-то вроде этого, что равняется 35 минутам.

#!/bin/bash
THEDATE=$(date +%s)
MYPID=$(ps aux|grep -v grep|egrep "MyProgram.exe"|awk '{print $2}')
if (( ${#MYPID} > 0 )); then
    STARTTIME=$(ls -ld /proc/$MYPID|date +%s -d"$(awk '{print $6, $7}')")
    TOTALMINS=$(( ($THEDATE - $STARTTIME) / 60  ))
    if (( $TOTALMINS >= 30 )); then
        kill -9 $MYPID
        logger -t "[KillLongRunningProcesses] Killed my program which had been running for $TOTALMINS minutes"
    fi
fi

При запуске из командной строки две переменные даты (THEDATE и STARTTIME) получают правильные значения. Но когда запускается cron, STARTTIME неверен. У него правильная дата, но, похоже, он игнорирует часть времени и устанавливает ее в полночь, то есть вместо «2009-12-14 13:23:00» получается «2009-12-14 00:00:00», что скидывает все расчеты.

Есть идеи? Спасибо.

Ответы [ 4 ]

2 голосов
/ 14 декабря 2009

Сначала никогда анализировать вывод ls, читать ЭТО , чтобы понять, почему. Далее, ваш сценарий может быть значительно улучшен с помощью pgrep вместо использования awk для анализа PID из grep на 'ps aux'. Кроме того, ваш сценарий ужасно ломается в случае, если вы вернули более одного PID. И наконец, при написании сценариев оболочки старайтесь не использовать ЗАГЛАВНЫЕ БУКВЫ для имен переменных; это соглашение зарезервировано для переменных, которые вы export вводите в свою среду.

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

#!/bin/bash

prog_name="MyProgram.exe"
the_date=$(date +%s)
my_pids=( $(pgrep "$prog_name") )

for ((i=0; i < ${#my_pids[@]}; i++)); do
    if [[ -d /proc/${my_pids[i]} ]]; then
        start_time=$(stat --printf=%Y /proc/${my_pids[i]})
        total_mins=$(( (the_date - start_time) / 60 ))
        if (( $total_mins >= 30 )); then
            kill -9 ${my_pids[i]}
            logger -t "Your custom message here"
        fi
    fi
done
2 голосов
/ 14 декабря 2009

Вот почему нельзя полагаться на разбор ls. Вы должны использовать stat, если она есть в вашей системе.

stat --printf=%Y /proc/$MYPID

Если нет, возможно, ваш find сможет сделать это за вас:

find /proc -maxdepth 1 -name $MYPID -printf "%T@"
0 голосов
/ 14 декабря 2009

Я понял, как это сделать. Если я использую аргумент "--time-style = long-iso" с ls, он возвращает его в нужном мне формате. Очевидно, cron имеет некоторые предпочтения для некоторых команд, чем пользователь по умолчанию.

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

0 голосов
/ 14 декабря 2009

Для чего я стоил, я привык к тому, что PATH и другие переменные среды не устанавливаются автоматически.

Стоит проверить. Если это не так, прокомментируйте, и я удалю свой ответ.

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