AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 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

Envie uma notificação ou alerta quando o bash solicitar a entrada do usuário

  • 772

Estou usando o Ubuntu 16.04 LTS. Existe um alias no my .bashrcque usa 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$//'\'')"'

Posso anexar alerta outros comandos como somecommand; alertou somecommand && alerte receber uma notificação pop-up após a somecommandconclusão (com sucesso). Isso me lembra que o comando que executei em uma janela do Terminal que agora está minimizado ou em um espaço de trabalho diferente terminou de ser executado.

Mas eu quero um alerta semelhante quando ele espera por uma entrada do usuário em vez de conclusão (por exemplo, prompt Sim/Não). Como eu posso fazer isso?

O uso de soluções análogas notify-sendseria ótimo, mas outra alternativa relativamente simples também seria boa.

Caso haja uma confusão, não pretendo criar uma resposta automática ao prompt. Eu só quero que me lembre de janelas de terminal esquecidas (minimizadas/em diferentes áreas de trabalho) enquanto executam comandos com saída longa que podem solicitar entrada do usuário (por exemplo apt update && apt upgrade, ).

bash shell
  • 2 2 respostas
  • 5386 Views

2 respostas

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

    Monitorar o diálogo de um programa e enviar um alerta

    Você pode monitorar a atividade de

    1. um fifo ou
    2. um xtermarquivo de log , agora com um modo interativo

    e deixá-lo iniciar uma zenitymensagem de informação , quando houver entrada do programa monitorado. Se desejar, você também pode instalar espeake deixá-lo enviar uma mensagem de áudio .

    1. Inicie uma zenitymensagem informativa, quando houver entrada de um programa monitorado usando um fifo.

    O shellscript a seguir pode monitorar o diálogo de saída de um programa e enviar um alerta.

    • assumindo um ambiente de desktop gráfico
    • inicie um shellscript wrapper em uma janela de terminal, que é usado como um 'console' parawrapper
    • iniciando o programa a ser monitorado em uma xtermjanela
    • executando o diálogo na xtermjanela (é onde você escreve sua entrada)
    • usando um fifo para ter acesso à saída do programa a ser monitorado, /dev/stdoute dev/stderr.
    • executando um whileloop
      • testando se o fifo foi modificado e nesse caso
        • iniciando uma zenityjanela de mensagem informativa.

    Espera-se que você feche a zenityjanela (pode trabalhar com 'Enter') para voltar à xtermjanela, onde você escreve sua entrada.

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

    Você pode querer correr espeakperto zenitypara receber uma mensagem de áudio também. Nesse caso, você pode remover o #caractere no início dessa linha. (Pode haver muito texto do programa, então geralmente é uma má ideia redirecionar o fifo para espeak. É melhor redirecionar o fifo para cate imprimi-lo no 'console'.)

    Demonstração

    Você pode testar algumas linhas de comando com cp -ie mv -ie você pode testar com o seguinte pequeno 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
    

    Texto de ajuda:

    $ ./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
    

    Monitoramento program:

    $ ./wrapper ./program
    

    zenityjanela de mensagem de informação:

    insira a descrição da imagem aqui

    Diálogo na xtermjanela:

    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
    

    Saída 'Console' na janela do terminal original após terminar:

    $ ./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
    

    Monitoramento cp -ip:

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

    zenityjanela de mensagem de informação:

    insira a descrição da imagem aqui

    Diálogo em xterm:

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

    Monitoramento sudo parted /dev/sdc:

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

    Diálogo em 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
    

    2. Iniciar uma zenitymensagem informativa, quando algo é escrito em uma xtermjanela (do programa monitorado ou do usuário).

    O shellscript a seguir pode monitorar o diálogo com um programa e enviar um alerta.

    • assumindo um ambiente de desktop gráfico
    • inicie um shellscript wrapper em uma janela de terminal, que é usado como um 'console' parawrapper
    • iniciando o programa a ser monitorado em uma xtermjanela
    • executando o diálogo na xtermjanela (é onde você escreve sua entrada)
    • usando um arquivo de log xtermpara obter acesso à saída e entrada do programa a ser monitorado
    • executando um whileloop
      • testando se o arquivo de log foi modificado e nesse caso
        • iniciando uma zenityjanela de mensagem informativa.
        • pequenos atrasos são permitidos durante a digitação da entrada (8 segundos; você pode editar o arquivo de script para alterar o tempo de atraso).

    Espera-se que você feche a zenityjanela (pode trabalhar com 'Enter') para voltar à xtermjanela, onde você escreve sua entrada.

    Agora existe um modo interativo, onde você usa a xtermjanela da mesma forma que usa qualquer janela de terminal. Feche a xtermjanela para interromper o monitoramento.

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

    Salve este bashcódigo em um arquivo e dê a ele [por exemplo] o nome vialog, torne-o executável e talvez mova-o para um diretório em seu caminho.

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

    Você trabalha na xtermjanela e o diálogo ecoa na janela inicial também.

    insira a descrição da imagem aqui

    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
    

    insira a descrição da imagem aqui

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

    Convite para feedback

    Em vez de adicionar outro shellscript à minha resposta já existente, acho que é melhor com uma segunda resposta. Vou ouvir os comentários e focar no script/método preferido e tentar mesclar o que é preferido em uma resposta (a menos que haja motivos para mantê-los todos (para diferentes propósitos).

    Monitorar o diálogo de um programa e enviar um alerta

    Você pode monitorar a atividade de

    1. um fifo ou
    2. um xtermarquivo de registro

    e deixá-lo iniciar uma zenitymensagem de informação , quando houver entrada do programa monitorado. Se desejar, você também pode instalar espeake deixá-lo enviar uma mensagem de áudio .

    Esta resposta se concentra em uma segunda alternativa usando um fifo .

    Start a zenity info message, when there is input from a monitored program using a fifo.

    1.1 Using xterm, monitoring standard output and standard error via a fifo

    This wrapper method has the

    • advantage, that no direct input will trigger the alert. This works well with many programs, for example cp -i and sudo.
    • disadvantage, that
      • some programs will be disabled, because they use not only standard output and standard error for writing its output. Example: sftp will lose the prompt, and the user cannot know, when the program is ready for a new task.
      • 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.

    Digite exitpara sair scripte viafifo. Depois disso, você pode obter um arquivo de log com todo o diálogo.

    viafifoé testado com

    • Ubuntu 18.04.1LTS . <---Você encontra ocódigo bashviafifo neste link .
    • Debian 9.6.0, 'Esticar'. Veja as seguintes capturas de tela e impressão de time viafifoe viafifo.log.

    Exemplo de demonstração

    Capturas de tela

    insira a descrição da imagem aqui

    insira a descrição da imagem aqui

    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

relate perguntas

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • Como salvar um caminho com ~ em uma variável?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

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

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve