Уведомление рабочего стола о завершении длительных команд

Я хотел бы получать уведомление на рабочем столе всякий раз, когда команда, которая выполняется более 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

SNAP1

Вы можете настроить псевдоним в соответствии с вашими потребностями и желаниями.

Помимо обертки, подобной предложенной 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,

Другие вопросы по тегам