Уведомление рабочего стола о завершении длительных команд
Я хотел бы получать уведомление на рабочем столе всякий раз, когда команда, которая выполняется более 15 секунд, завершается в интерактивной оболочке.
Другими словами, я бы хотел, чтобы все команды были обернуты примерно так
start=$(date +%s);
ORIGINAL_COMMAND;
[ $(($(date +%s) - start)) -le 15 ] || notify-send "Long running command finished"
Какой лучший способ сделать это в bash?
9 ответов
Вы хотите https://launchpad.net/undistract-me (устанавливается из архивов Ubuntu с sudo apt-get install undistract-me
) который выполняет именно то, что вы просите, в том числе работает автоматически (то есть, не забывая добавлять что-то дополнительное к потенциально длительным командам).
Насколько я понял, вы хотите обертку. И вы хотите использовать команду через нее, чтобы она выдала вам желаемое уведомление, если время выполнения вашей команды превышает 15 секунд. Так вот и все.
wrapper(){
start=$(date +%s)
"$@"
[ $(($(date +%s) - start)) -le 15 ] || notify-send "Notification" "Long\
running command \"$(echo $@)\" took $(($(date +%s) - start)) seconds to finish"
}
Скопируйте эту функцию в свой ~/.bashrc
и источник ~/.bashrc
как,
. ~/.bashrc
Useage
wrapper <your_command>
Если это займет более 15 секунд, вы получите уведомление на рабочем столе, описывающее команду и время ее выполнения.
пример
wrapper sudo apt-get update
В ~/.bashrc
есть псевдоним alert
определяется как:
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
который может быть использован для уведомления о завершении выполнения команды.
Использование:
$ the_command; alert
например
$ sudo apt-get update; alert
Вы можете настроить псевдоним в соответствии с вашими потребностями и желаниями.
Помимо обертки, подобной предложенной souravc, на самом деле нет хорошего способа сделать это в bash. Вы можете обойти это, используя ловушку DEBUG и PROMPT_COMMAND. Ловушка DEBUG срабатывает всякий раз, когда вы запускаете команду, и PROMPT_COMMAND запускается непосредственно перед написанием приглашения.
Так что вещи для ~/.bashrc
становится чем-то вроде
trap '_start=$SECONDS' DEBUG
PROMPT_COMMAND='(if (( SECONDS - _start > 15 )); then notify-send "Long running command ended"; fi)'
Это хак, так что не удивляйтесь, если с этим столкнетесь со странными побочными эффектами.
РЕДАКТИРОВАТЬ
TL; DR: создать ярлык автозаполнения в .inputrc
и функционировать в .bashrc
, Запустите команду как обычно, введите, но вместо ENTER нажмите ярлык, который вы указали в .inputrc
Человек, который назначил награду за этот вопрос, сказал:
"Все существующие ответы требуют ввода дополнительной команды после команды. Мне нужен ответ, который делает это автоматически".
При исследовании решений этой проблемы я наткнулся на этот вопрос из stackexchange, который позволяет связать CtrlJ с последовательностью команд: Ctrla (перейти к началу строки), поместить строку "mesure" перед введенной вами командой., Ctrlm (выполнить)
Таким образом, вы получаете функциональность автозаполнения и отдельную команду ENTER для измерения времени, сохраняя при этом первоначальную цель второй функции, которую я опубликовал ниже.
На данный момент, вот содержимое моего ~/.inputrc
файл:
"\C-j": "\C-a measure \C-m"
А вот и содержание .bashrc
(заметьте, я не использовал bash вечно - я использую mksh в качестве оболочки, следовательно, это то, что вы видите в оригинальном посте. Функциональность все та же)
PS1=' serg@ubuntu [$(pwd)]
================================
$ '
function measure ()
{
/usr/bin/time --output="/home/xieerqi/.timefile" -f "%e" $@
if [ $( cat ~/.timefile| cut -d'.' -f1 ) -gt 15 ]; then
notify-send "Hi , $@ is done !"
fi
}
Оригинальный пост
Вот моя идея - использовать функцию в .bashrc
, Основной принцип - использование /usr/bin/time
для измерения времени, необходимого для выполнения команды, и, если оно превышает 15 секунд, отправьте уведомление.
function measure ()
{
if [ $( /usr/bin/time -f "%e" $@ 2>&1 >/dev/null ) -gt 15 ]; then
notify-send "Hi , $@ is done !"
fi
}
Здесь я перенаправляю вывод на /dev/null
но для просмотра выходных данных можно также выполнить перенаправление в файл.
ИМХО, гораздо лучший подход - отправлять вывод времени в какой-то файл в вашей домашней папке (просто чтобы вы не загрязняли вашу систему временными файлами и всегда знали, где искать). Вот эта вторая версия
function measure ()
{
/usr/bin/time --output=~/.timefile -f "%e" $@
if [ $( cat ~/.timefile | cut -d'.' -f1 ) -gt 15 ]; then
notify-send "Hi , $@ is done !"
fi
}
А вот скриншоты первой и второй версии, в таком порядке
Первая версия, нет вывода
Вторая версия, с выходом
Я недавно создал инструмент, который служит этой цели. Он может быть запущен как оболочка или автоматически с интеграцией оболочки. Проверьте это здесь: http://ntfy.rtfd.io/
Чтобы установить это:
sudo pip install ntfy
Чтобы использовать его в качестве оболочки:
ntfy done sleep 3
Чтобы получать уведомления автоматически, добавьте это в свой .bashrc
или же .zshrc
:
eval "$(ntfy shell-integration)"
Вы можете изменить Bash для реализации нужной вам функциональности оболочки.
Если вы склонны делать много таких модификаций в вашей интерактивной оболочке, вы можете подумать о переключении на внутренне взломанную оболочку, например eshell, которая построена с использованием Emacs elisp и имеет все свои легендарные возможности настройки:
http://www.masteringemacs.org/articles/2010/12/13/complete-guide-mastering-eshell/
Ваш сценарий работает довольно хорошо, просто убедитесь, что вы включили "Шебанг" ( #!/bin/bash
) линия. Другие, чтобы #!/bin/bash
упоминаются здесь, но большую часть времени, #!/bin/bash
отлично работает для сценариев Unix Bash. Это требуется интерпретатору сценария, чтобы он знал, какой это тип сценария.
Это похоже на тестовый скрипт:
#!/bin/bash
start=$(date +%s);
echo Started
sleep 20;
echo Finished!
[ $(($(date +%s) - start)) -le 15 ] || notify-send -i dialog-warning-symbolic "Header" "Message"
Чтобы изменить этот сценарий, поместите команду (и), где echo
а также sleep
линии есть.
Обратите внимание, с notify-send
, ты можешь использовать -i
указать и иконку:-)
Кроме того, убедитесь, что он исполняется, запустив chmod +x /PATH/TO/FILE
на это первым.
Вы также можете сделать это с помощью простого оператора, как это
#!/bin/bash
START=$(date +%s)
TIME=$(($START+15))
ORIGINAL_COMMAND;
END=$(date +%s)
if [ $END -gt $TIME ]
then
notify-send "Task Completed"
fi
Вы можете использовать свои собственные имена переменных.
Я могу подтвердить, что это работает, я проверил с помощью команды, которая занимает много времени, а другая - нет, и уведомление приходит для команды, которая занимает много времени.
Вы также можете сделать это с любой командой, заменив ORIGINAL_COMMAND
с $@
и запустить скрипт как ./script command
,