AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 491121
Accepted
pomsky
pomsky
Asked: 2018-12-28 05:01:55 +0800 CST2018-12-28 05:01:55 +0800 CST 2018-12-28 05:01:55 +0800 CST

当 bash 要求用户输入时发送通知或警报

  • 772

我正在使用 Ubuntu 16.04 LTS。我有一个别名,.bashrc它使用notify-send:

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$//'\'')"'

我可以附加alert到其他命令作为somecommand; alertor并在完成后(成功)somecommand && alert获得弹出通知。somecommand它提醒我,我在终端窗口中运行的命令现在已最小化或在不同的工作区中已完成执行。

但是当它等待用户输入而不是完成时(例如是/否提示),我想要一个类似的警报。我怎样才能做到这一点?

使用类似的解决方案notify-send会很好,但其他相对简单的替代方案也可以。

万一出现混淆,我不打算创建对提示的自动回复。我只是想让它提醒我忘记(最小化/在不同的工作区中)终端窗口,同时运行具有冗长输出的命令,这些命令可能要求用户输入(例如apt update && apt upgrade)。

bash shell
  • 2 2 个回答
  • 5386 Views

2 个回答

  • Voted
  1. Best Answer
    sudodus
    2018-12-28T21:57:53+08:002018-12-28T21:57:53+08:00

    监视程序的对话并发送警报

    您可以监控的活动

    1. 先进先出或_
    2. 一个xterm日志文件,现在具有交互模式

    并让它启动一条zenity信息消息,当有来自受监视程序的输入时。如果您愿意,您还可以安装espeak并让它发送音频消息。

    1.zenity当使用 fifo 的受监控程序有输入时,启动一条信息消息。

    以下 shellscript 可以监视程序的输出对话并发送警报。

    • 假设图形桌面环境
    • 在终端窗口中启动一个包装器 shellscript,它就像一个“控制台”用于wrapper
    • xterm在窗口中启动要监控的程序
    • xterm在窗口中运行对话(这是您编写输入的地方)
    • 使用 fifo 访问要监控的程序的输出,/dev/stdout以及dev/stderr.
    • 运行while循环
      • 测试fifo是否已被修改,在这种情况下
        • 启动zenity信息消息窗口。

    您应该关闭zenity窗口(可以使用“Enter”)以返回到xterm您输入输入的窗口。

    #!/bin/bash
    
    if [ $# -eq 0 ]
    then
     echo "'$0' is a wrapper, that sends a notification, when the wrapped program
    has written to standard input and standard error and may be waiting for input.
    ---
    Usage:   $0 <program name> [parameters]
    Example: $0 .program"
     exit
    fi
    
    message="'${1##*/} $2 ...' has written something, maybe asks for input"
    
    tmpdir=$(mktemp -d)
    tmpfifo=$(mktemp --tmpdir=$tmpdir)
    rm "$tmpfifo"
    mkfifo "$tmpfifo"
    #ls -l "$tmpdir"
    cnt1=$(stat --printf "%Y" "$tmpfifo")
    sleep 1
    
    xterm -title "${1##*/} $2 ..." -fa default -fs 11 -bg '#403600' \
     -e bash -c "$* 2>&1 | tee /dev/stderr 2>&1 > $tmpfifo" 2> /dev/null & pid=$!
    
    #< "$tmpfifo" espeak &
    < "$tmpfifo" cat &
    
    cont=true
    while $cont
    do
     tmpstr=$(ps -Af |sed "s/grep $pid//"|grep "$pid")
    # echo "$tmpstr"
     if [ "$tmpstr" != "" ]
     then
      cnt0=$cnt1
      cnt1=$(stat --printf "%Y" "$tmpfifo")
      if [ "$cnt1" != "$cnt0" ]
      then
    #   zenity --notification --text="$message" 2> /dev/null
    #   espeak "$message" &
       zenity --info --title="${0##*/} ${1##*/} $2 ..." \
        --text="$message" --width=500  2> /dev/null
      fi
      sleep 1
      else
      sleep .2
      # echo "process $pid has finished"
      cont=false
     fi
    done
    
    # clean up
    
    rm -r "$tmpdir"
    

    您也可能希望跑到espeak附近zenity以获取音频消息。在这种情况下,您可以删除该#行开头的字符。(程序中可能有很多文本,因此将 fifo 重定向到 通常是个坏主意espeak。最好将 fifo 重定向到cat并将其打印在“控制台”中。)

    演示

    cp -i您可以使用and测试一些命令行,mv -i并且可以使用以下小 shellscript 进行测试program,

    #!/bin/bash
    
    while true
    do
     read -p "Waiting for input. 'Stop' to Quit " string
     if [ "${string:0:4}" == "Stop" ]
     then
      printf "$string. Gotcha\n"
      break
     elif [ "$string" != "" ]
     then
      printf "$string\n"
      printf "Working for 10 seconds ...\n"
      sleep 10
     else 
      sleep 3
     fi
    done
    

    帮助文字:

    $ ./wrapper
    './wrapper' is a wrapper, that sends a notification, when the wrapped program
    has written to standard input and standard error and may be waiting for input.
    ---
    Usage:   ./wrapper <program name> [parameters]
    Example: ./wrapper .program
    

    监控program:

    $ ./wrapper ./program
    

    zenity信息消息窗口:

    在此处输入图像描述

    xterm窗口对话:

    Waiting for input. 'Stop' to Quit Hello
    Hello
    Working for 10 seconds ...
    Waiting for input. 'Stop' to Quit World
    World
    Working for 10 seconds ...
    Waiting for input. 'Stop' to Quit Goodbye
    Goodbye
    Working for 10 seconds ...
    Waiting for input. 'Stop' to Quit Stop
    

    完成后在原始终端窗口中的“控制台”输出:

    $ ./wrapper ./program
    Waiting for input. 'Stop' to Quit Hello
    Working for 10 seconds ...
    Waiting for input. 'Stop' to Quit World
    Working for 10 seconds ...
    Waiting for input. 'Stop' to Quit Goodbye
    Working for 10 seconds ...
    Waiting for input. 'Stop' to Quit Stop. Gotcha
    

    监控cp -ip:

    $ LANG=C /path/wrapper cp -ip ubuntustudio-18.04-dvd-amd64.iso ubuntu-18.04.1-desktop-amd64.iso /tmp
    

    zenity信息消息窗口:

    在此处输入图像描述

    对话xterm:

    cp: overwrite '/tmp/ubuntustudio-18.04-dvd-amd64.iso'? y
    cp: overwrite '/tmp/ubuntu-18.04.1-desktop-amd64.iso'? n
    

    监控sudo parted /dev/sdc:

    $ LANG=C ./wrapper sudo parted /dev/sdc
    

    对话xterm:

    [sudo] password for sudodus: 
    GNU Parted 3.2
    Using /dev/sdc
    Welcome to GNU Parted! Type 'help' to view a list of commands.
    (parted) p                                                                
    Model: SanDisk Extreme (scsi)
    Disk /dev/sdc: 16,0GB
    Sector size (logical/physical): 512B/512B
    Partition Table: msdos
    Disk Flags: 
    
    Number  Start   End     Size    Type      File system  Flags
     3      2097kB  258MB   256MB   primary   fat32        boot
     4      258MB   1366MB  1108MB  primary
     2      1366MB  12,4GB  11,0GB  extended               lba
     5      1367MB  6736MB  5369MB  logical   ext2
     6      6737MB  12,4GB  5615MB  logical   ext4
     1      12,4GB  16,0GB  3662MB  primary   ntfs
    
    (parted) q
    

    zenity2.当有东西被写入xterm窗口时(来自被监控的程序或来自用户) ,启动一条信息消息。

    以下 shellscript 可以监视与程序的对话并发送警报。

    • 假设图形桌面环境
    • 在终端窗口中启动一个包装器 shellscript,它就像一个“控制台”用于wrapper
    • xterm在窗口中启动要监控的程序
    • xterm在窗口中运行对话(这是您编写输入的地方)
    • 使用日志文件xterm来访问要监视的程序的输出和输入
    • 运行while循环
      • 测试日志文件是否已被修改,在这种情况下
        • 启动zenity信息消息窗口。
        • 在输入输入期间允许短暂的延迟(8 秒;您可以编辑脚本文件以更改延迟时间)。

    您应该关闭zenity窗口(可以使用“Enter”)以返回到xterm您输入输入的窗口。

    现在有一个交互模式,您可以xterm像使用任何终端窗口一样使用该窗口。关闭xterm窗口以停止监控。

    #!/bin/bash
    
    # date        editor   comment
    # 2018-12-31  sudodus  version 1.0
    
    version=1.0
    
    name="${0##*/}"
    if [ "$1" == "-h" ] || [ "$1" == "--help" ]
    then
     echo "'$name' is a wrapper, that sends a notification, when the wrapped program
    has written to standard input and standard error and may be waiting for input.
    ---
    Usage:    $name [program name] [parameters]
    Examples: $name          # to run program(s) interactively in an xterm window
              $name program
              $name -h       # to get help (this text)
              $name -v       # show version"
     exit
    elif [ "$1" == "-v" ]
    then
     echo "$name version $version"
     exit
    fi
    tstart=$(date '+%s')
    echo "----- start $name at $(date '+%F %T') ----------------------------"
    tmpstr="${1##*/}"
    xtermlog=$(mktemp -u)
    
    if [ $# -eq 0 ]
    then
     mess_zenity="Check, if the monitored program asks for input"
     mess_espeak="${mess_zenity/program/, Program,}"
     xterm -title "monitored by ${0##*/}" -fa default -fs 11 -bg '#2c2b2a' \
     -l -lf "$xtermlog" -sb -rightbar 2> /dev/null & pid=$!
    else
     mess_espeak="Check if '${tmpstr^} ${2##*/} ${3##*/} ...' asks for input"
     mess_zenity="Check if '$tmpstr $2 $3 ...' asks for input"
     xterm -title "${1##*/} $2 $3 ..." -fa default -fs 11 -bg '#2c2b2a' \
     -l -lf "$xtermlog" -e "$@" 2> /dev/null & pid=$!
    fi
    sleep 0.5
    sync
    cnt1=$(stat --printf "%Y" "$xtermlog")
    tail -f "$xtermlog" & ptail=$!
    
    cont=true
    while $cont
    do
     sleep 1
     cnt0=$cnt1
     tmpstr=$(ps -Af |sed "s/grep $pid//"|grep "$pid")
    # echo "$tmpstr"
     if [ "$tmpstr" != "" ]
     then
      cnt1=$(stat --printf "%Y" "$xtermlog")
      if [ $cnt1 -gt $((cnt0 + 8)) ]
      then
    #   zenity --notification --text="$message" 2> /dev/null
       espeak "$mess_espeak" &
       zenity --info --title="${0##*/} ${1##*/} $2 ..." \
        --text="$mess_zenity" --width=500  2> /dev/null
       touch "$xtermlog"
       cnt1=$(stat --printf "%Y" "$xtermlog")
      fi
      sleep 1
      else
      sleep .2
      # echo "process $pid has finished"
      cont=false
     fi
    done
    
    # clean up
    tmpstr="$(tail -n1 "$xtermlog" | sed 's/.*exit.*/exit/')"
    if [ "$tmpstr" != "exit" ]
    then
     echo ""
    fi
    rm -r "$xtermlog"
    kill $ptail
    tend=$(date '+%s')
    tuse=$((tend-tstart))
    echo "------- end $name at $(date '+%F %T') --- used $tuse seconds"
    

    将这段bash代码保存到一个文件中,并给它[例如]名称vialog,使其可执行,并可能将其移动到您路径中的目录中。

    $ vialog
    ----- start vialog at 2018-12-31 14:37:41 ----------------------------
    

    您在xterm窗口中工作,对话也会回显到起始窗口。

    在此处输入图像描述

    sudodus@bionic64 /media/multimed-2/test/test0/pomsky-wrap $ ./program
    Waiting for input. 'Stop' to Quit Hello World
    Hello World
    Working for 10 seconds ...
    Waiting for input. 'Stop' to Quit I am writing ...
    I am writing ...
    Working for 10 seconds ...
    Waiting for input. 'Stop' to Quit Stop
    Stop. Gotcha
    sudodus@bionic64 /media/multimed-2/test/test0/pomsky-wrap $ scrot -sb
    sudodus@bionic64 /media/multimed-2/test/test0/pomsky-wrap $ exit
    exit
    ------- end vialog at 2018-12-31 14:39:02 --- used 81 seconds
    

    在此处输入图像描述

    • 2
  2. sudodus
    2019-01-06T21:47:31+08:002019-01-06T21:47:31+08:00

    邀请反馈

    我认为最好使用第二个答案,而不是在我已经存在的答案中添加另一个 shellscript。我将听取反馈并专注于首选的脚本/方法,并尝试将首选的内容合并到一个答案中(除非有理由将它们全部保留(出于不同目的)。

    监视程序的对话并发送警报

    您可以监控的活动

    1. 先进先出或_
    2. 一个xterm日志文件

    并让它启动一条zenity信息消息,当有来自受监视程序的输入时。如果您愿意,您还可以安装espeak并让它发送音频消息。

    这个答案侧重于使用fifo的第二种选择。

    zenity当使用 fifo 的受监视程序有输入时,启动一条信息消息。

    1.1 使用xterm,通过fifo监控标准输出和标准错误

    该wrapper方法具有

    • 优点是没有直接输入会触发警报。这适用于许多程序,例如cp -i和sudo.
    • 劣势,即
      • 某些程序将被禁用,因为它们不仅使用标准输出和标准错误来写入其输出。示例:sftp将丢失提示,并且用户无法知道程序何时准备好执行新任务。
      • some programs echo the input (there is indirect input), and this will trigger the alert, which may cause a lot of alerts in a shellscript, that does not take that into account. Example: ssh.

    1.2 Using the compiled program script and its log file via a fifo

    The following shellscript can monitor the output dialogue from a program and send an alert. It needs espeak and script (script need not be installed in Ubuntu and Debian).

    sudo apt update
    sudo apt install espeak
    
    • assuming a graphical desktop environment
    • start a shellscript in a terminal window, let us call it viafifo.
    • starting the program to be monitored 'in viafifo'
    • running the dialogue in the terminal window (that is where you write your input)
    • using a fifo to get access to the output of the program to be monitored, /dev/stdin, /dev/stdout and dev/stderr. The main task in the shellscript is the line with the program script, that is monitoring the activity in the terminal window and writing to the fifo.
    • running a while loop
      • testing if the fifo has been modified and in that case
        • starting a zenity info message window and a correspoding spoken message with espeak.
        • short delays are allowed during typing the input (8 seconds; you can edit the script file to change the delay time).

    You are expected to close the zenity window (can work with 'Enter') to get back to the xterm window, where you write your input.

    键入exit离开script和viafifo。之后,您可以获得包含整个对话的日志文件。

    viafifo经测试

    • Ubuntu 18.04.1 LTS。您可以在此链接中<---找到bash 代码。viafifo
    • Debian 9.6.0,“拉伸”。请参阅以下屏幕截图和 和 的打印time viafifo输出viafifo.log。

    演示示例

    截图

    在此处输入图像描述

    在此处输入图像描述

    time viafifo

    user@debian:~$ time viafifo
    ----- Start viafifo ------------------------------------------------------------
    user@debian:~$ echo hello
    hello
    user@debian:~$ exit
    exit
    ----- End viafifo --------------------------------------------------------------
    See 'viafifo.log'
    viafifo used 8 seconds plus a few (5-10) seconds for preparing and finishing
    real    0m13.295s
    user    0m0.104s
    sys 0m0.012s
    

    viafifo.log

    user@debian:~$ cat viafifo.log
    Script started on Sat 05 Jan 2019 07:57:45 PM UTC
    user@debian:~$ echo hello
    hello
    user@debian:~$ exit
    exit
    viafifo used 8 seconds
    user@debian:~$ 
    
    • 1

相关问题

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • 如何将带有〜的路径保存到变量中?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve