5

Это длинный выстрел - я не думаю, что это возможно, но я решил спросить.

Я часто запускаю команды, выполнение которых занимает несколько минут, и пока они выполняются, я проверяю свою электронную почту или просматриваю Интернет. Когда я помню, я запускаю command; finished где finished это команда , которая всплывает диалоговое окно с уведомлением о том , что команда выполнена. Тем не менее, я не всегда помню, так что я хотел бы иметь что - то , что автоматически определяет , когда команда занимает более N секунд и пробеги finished , когда процесс завершается. Если это имеет значение, я предпочитаю использовать zsh, но я бы переключился, если бы другая оболочка была способна на это.

iTerm (эмулятор терминала для OSX) имеет такую функцию, где он показывает вам уведомление, когда терминал бездействует или выдает вывод после простоя в течение некоторого времени. Если есть какие-либо эмуляторы терминала для Linux, о которых вы знаете, которые имеют эту функцию, это будет работать так же хорошо (или лучше).

Можете ли вы придумать, как сделать эту работу? Спасибо!

2 ответа2

4

Вам нужен способ найти свои процессы, которые выполнялись некоторое время. Для этого полезно знать, что параметр etime показывает время, прошедшее с начала процесса, в формате DD-чч: мм: сс, где каждая большая часть является необязательной. Итак, вы можете сделать

ps -U sauer -o etime,pid,command

(в AIX вы можете использовать ps -U sauer -o "%t,%p,%c")

Вы можете использовать -t $( tty) вместо имени -U username для выбора процессов в текущем tty (или в текущем терминале). Это то, что я сделаю позже. Также обратите внимание, что выполнение -o cmd= подавляет заголовок столбца, но означает, что вам нужно несколько параметров -o.

Таким образом, вы получите команду ps -t $(tty) -o etime= -o pid= -o command= чтобы показать все процессы, запущенные на текущем терминале, со столбцами "истекшее время настенных часов", "идентификатор процесса" и "команда" и подавление заголовков столбцов.

Теперь вам нужно получить только те, которые работали дольше, чем любые секунды. Итак, вам нужно извлечь первый столбец и преобразовать время в секунды. Как насчет сценария оболочки, чтобы сделать это (ksh/bash):

ps -t $(tty) -o etime= -o pid= -o command= | while read time pid cmd
do
  secs=0
  while true
  do
    part=${time##*:}
    secs=$(( secs + ${part#0} ))
    [[ "$part" != "$time" ]] || break # only had seconds

    time=${time%:$part}
    part=${time##*:}
    secs=$(( secs + (60 * ${part#0}) ))
    [[ "$part" != "$time" ]] || break # only had minutes left

    time=${time%:$part}
    part=${time##*-}
    secs=$(( secs + (60 * 60 * ${part#0}) ))
    [[ "$part" != "$time" ]] || break # only had hours left

    time=${time%-$part} # all that's left are days-hours
    secs=$(( secs + (24 * 60 * 60 * time) ))
    break
  done

  echo "Process '$cmd' (pid '$pid') has been up for '$secs' seconds"
done

Пара вещей, возможно, потребуется объяснить. ${part#0} находится там, так что времена, такие как "06" секунд, преобразуются в "6" вместо того, чтобы рассматриваться как восьмеричные. Конечно, восьмеричное 06 и десятичное 6 одинаковы, но восьмеричное 09 недопустимо, и снаряды иногда жалуются на это.

Другая вещь состоит в том, что ${var##*:} оценивается как $ var с наибольшей строкой, совпадающей с "*:", обрезанной спереди (один # - самое короткое совпадение, а %% / % делает то же самое с конец). Если шаблон не совпадает, он оценивается в $var . Таким образом, мы вытягиваем все, кроме секунд, добавляем это к секундам, а затем удаляем секунды с конца. Если у нас есть вещи, это минуты. Итак, восстановите минуты, переведите их в секунды, добавьте к промежуточному итогу, обрежьте его с конца. И так далее.

Хорошо. Оттуда, теперь вам просто нужно поставить #!/bin/ksh (или bash, если нужно) вверху, и у вас есть скрипт. Кроме того, вам также нужен способ найти только те пиды, которые работают более X секунд. Как насчет файла в /tmp. Давайте использовать это вместо команды echo:

  if [[ $secs -gt 120 ]]
  then
    { cat /tmp/pids.$$; echo "$pid $cmd"; } 2>/dev/null | sort -u > /tmp/pids.$$.tmp
    while read p c
    do
      if ps -p $p >/dev/null 2>&1
      then
        # put it back in the list
        echo "$p $c" > /tmp/pids.$$
      else
        echo "Command '$c' exited" | mailx -s "exit report" $USER
      fi
    done < /tmp/pids.$$.tmp
  fi

Теперь все, что вам нужно сделать, это обернуть всю гигантскую вещь внутри цикла

в то время как true делает # большой цикл while и оператор if 10 sleep

Назовите это process_monitor.sh и вставьте process_monitor.sh& в ваш .profile или .bash_login или что-то еще. Это будет происходить в фоновом режиме, наблюдая за всеми процессами в этом терминале, и когда он найдет один запущенный более 120 секунд, он добавит его в список, чтобы посмотреть, и отправит вам электронное письмо, когда процесс завершится.

Есть вещи, которые я, вероятно, добавлю, чтобы сделать его более красивым, например, захват сигнала EXIT, удаление временных файлов при выходе из скрипта и т.д. Но это упражнение для тебя. Надеюсь, этого должно быть достаточно, чтобы вы поправились. :)

2

Я только что попробовал небольшое приложение, которое делает именно то, что вы хотите:https://github.com/jml/undistract-me, доступный в мире Debian/Ubuntu в виде пакета. Он не работал для меня, пока я не перезапустил Konsole, который является моим предпочтительным приложением с вкладками для терминала.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .