Я хотел бы получать уведомление на рабочем столе всякий раз, когда команда, которая выполняется более 15 секунд, завершается в интерактивной оболочке.
Другими словами, я хотел бы, чтобы все команды были заключены в нечто подобное
start=$(date +%s);
ORIGINAL_COMMAND;
[ $(($(date +%s) - start)) -le 15 ] || notify-send "Long running command finished"
Каков наилучший способ сделать это в bash?
Вы хотите 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
Использование
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 kbd> нажмите ярлык, который вы указали в .inputrc
Человек, который назначил награду за этот вопрос, сказал:
«Все существующие ответы требуют ввода дополнительной команды после команды. Я хочу получить ответ, который делает это автоматически».
При исследовании решений этой проблемы я наткнулся после этого вопроса из stackexchange, который позволяет связать Ctrl kbd> J kbd> с последовательностью команд: Ctrl kbd> a < / kbd> (перейти к началу строки), поместить строку «mesure» перед введенной вами командой, Ctrl kbd> m kbd> (execute)
Таким образом вы получаете функциональность автозаполнения и отдельную команду ENTER kbd> для измерения времени, сохраняя при этом первоначальное назначение функции секунд , о которой я писал ниже.
На данный момент вот содержимое моего ~/.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
}
А вот скриншоты первой и второй версии, в том порядке
Первая версия, без вывода
Вторая версия, с выводом
Я недавно создал инструмент, который служит этой цели. Он может быть запущен как оболочка или автоматически с интеграцией оболочки. Проверьте это здесь: http://ntfy.rtfd.io
Чтобы установить его:
sudo pip install ntfy
Чтобы использовать его в качестве оболочки:
ntfy done sleep 3
Чтобы получать уведомления автоматически, добавьте это в .bashrc
или .zshrc
:
eval "$(ntfy shell-integration)"
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
. sup>
Обратите внимание, что с notify-send
вы также можете использовать -i
для указания значка: -)
Также, убедитесь, что он исполняется, запустив chmod +x /PATH/TO/FILE
на это первым.
Вы можете изменить Bash для реализации нужной вам функции оболочки.
Если вы склонны делать много таких модификаций в вашей интерактивной оболочке, вы можете подумать о переключении на внутренне взломанную оболочку, например eshell, которая построена с использованием Emacs elisp и имеет все свои настраиваемые параметры:
http://www.masteringemacs.org/articles/2010/12/13/complete-guide-mastering-eshell/
Вы также можете сделать это с помощью простого оператора 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
.