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

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

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

start=$(date +%s);
ORIGINAL_COMMAND;
[ $(($(date +%s) - start)) -le 15 ] || notify-send "Long running command finished"

Каков наилучший способ сделать это в bash?

59
задан 5 May 2017 в 06:46

9 ответов

Вы хотите https://launchpad.net/undistract-me (устанавливается из архивов Ubuntu с помощью sudo apt-get install undistract-me), который выполняет именно то, что вы запрашиваете, включая автоматическую работу (то есть без необходимости добавлять что-то дополнительное к потенциально длительным командам).

0
ответ дан 5 May 2017 в 06:46

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

Использование

wrapper <your_command>

Если через 15 секунд вы получите уведомление на рабочем столе, описывающее команду и время ее выполнения.

Пример

wrapper sudo apt-get update

screenshot of desktop-nitification

0
ответ дан 5 May 2017 в 06:46

В ~/.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

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

0
ответ дан 5 May 2017 в 06:46

Кроме обертки, как предположил 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)'

Это хак, поэтому не удивляйтесь, если вы столкнетесь с странными побочными эффектами.

0
ответ дан 5 May 2017 в 06:46

РЕДАКТИРОВАТЬ

TL; DR : создать ярлык автозаполнения в .inputrc и функцию в .bashrc. Запустите команду как обычно, введите, но вместо ENTER нажмите ярлык, который вы указали в .inputrc

Человек, который назначил награду за этот вопрос, сказал:

«Все существующие ответы требуют ввода дополнительной команды после команды. Я хочу получить ответ, который делает это автоматически».

При исследовании решений этой проблемы я наткнулся после этого вопроса из stackexchange, который позволяет связать Ctrl J с последовательностью команд: Ctrl a < / kbd> (перейти к началу строки), поместить строку «mesure» перед введенной вами командой, Ctrl m (execute)

Таким образом вы получаете функциональность автозаполнения и отдельную команду 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


}

Original Post

Вот моя идея - использовать функцию из .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, но для просмотра вывода перенаправление в файл также может быть выполнено.

Гораздо лучший подход, IMHO, это посылать вывод времени в какой-то файл в вашей домашней папке (просто чтобы вы не загрязняли вашу систему временными файлами и всегда знали, где искать). Вот эта вторая версия

function measure () 
{

/usr/bin/time --output=~/.timefile -f "%e" $@ 

if [ $( cat ~/.timefile | cut -d'.' -f1 ) -gt 15 ]; then

    notify-send "Hi , $@ is done !"

fi


}

А вот скриншоты первой и второй версии, в том порядке

Первая версия, без вывода enter image description here

Вторая версия, с выводом enter image description here

0
ответ дан 5 May 2017 в 06:46

Я недавно создал инструмент, который служит этой цели. Он может быть запущен как оболочка или автоматически с интеграцией оболочки. Проверьте это здесь: http://ntfy.rtfd.io

Чтобы установить его:

sudo pip install ntfy

Чтобы использовать его в качестве оболочки:

ntfy done sleep 3

Чтобы получать уведомления автоматически, добавьте это в .bashrc или .zshrc:

eval "$(ntfy shell-integration)"
0
ответ дан 5 May 2017 в 06:46
  • 1
    Когда я работаю lp, я добираюсь lp: Error - scheduler not responding.. – Ionică Bizău 14 July 2015 в 12:04

Ваш сценарий работает довольно хорошо, просто убедитесь, что вы включили строку 'shebang' (#!/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 на это первым.

0
ответ дан 5 May 2017 в 06:46

Вы можете изменить Bash для реализации нужной вам функции оболочки.

Если вы склонны делать много таких модификаций в вашей интерактивной оболочке, вы можете подумать о переключении на внутренне взломанную оболочку, например eshell, которая построена с использованием Emacs elisp и имеет все свои настраиваемые параметры:

http://www.masteringemacs.org/articles/2010/12/13/complete-guide-mastering-eshell/

0
ответ дан 5 May 2017 в 06:46

Вы также можете сделать это с помощью простого оператора if, подобного этому

#!/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.

0
ответ дан 5 May 2017 в 06:46

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

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