OSX bash, comando 'watch'

292

Estou procurando a melhor maneira de duplicar o comando 'watch' do Linux no Mac OSX. Eu gostaria de executar um comando a cada poucos segundos para fazer a correspondência de padrões no conteúdo de um arquivo de saída usando 'tail' e 'sed'.

Qual é a minha melhor opção em um Mac e isso pode ser feito sem o download de software?

joseph.hainline
fonte
2
Por que você deseja duplicá-lo quando você pode apenas instalá-lo?
Andrew Marshall
3
porque eu teria que configurar todos os Macs no escritório que o usuário o meu script
joseph.hainline
Sugiro que o seu script instale o brew e depois assista.
áster
O relógio de cerveja parece não pegar comandos no meu caminho ou pseudônimos.
sam boosalis
Como alternativa a um comando, você também pode usar o aplicativo /Applications/Utilities/Console.app para monitorar arquivos de log. Permite filtrar com pesquisa básica
JuanMa Cuevas

Respostas:

335

Você pode emular a funcionalidade básica com o loop do shell:

while :; do clear; your_command; sleep 2; done

Isso fará um loop para sempre, limpe a tela, execute seu comando e aguarde dois segundos - a watch your_commandimplementação básica .

Você pode dar um passo adiante e criar um watch.shscript que possa aceitar your_commande sleep_durationcomo parâmetros:

#!/bin/bash
# usage: watch.sh <your_command> <sleep_duration>

while :; 
  do 
  clear
  date
  $1
  sleep $2
done
Daniel Pittman
fonte
2
Eu acredito que o relógio mostra apenas a primeira tela cheia de saída. Se você quiser fazer algo semelhante, mude your_commandparayour_command 2>&1|head -10
Mark Eirich 10/11
10
Isso funciona muito bem, mas eu prefiro sleep ${2:-1}tornar o intervalo opcional.
Daniel Lubarov
2
Além disso, é echo "$(date)"equivalente a date?
Daniel Lubarov
5
Também não funciona com tubos. Aqui está um garfo com várias melhorias: daniel.lubarov.com/simple-watch-script-for-osx
Daniel Lubarov
Não funciona como watchquando a saída é mais de uma tela. Mostra apenas o final, enquanto watchmostra apenas o topo. (Nem é o ideal)
h__ 05/02
545

Com o Homebrew instalado:

brew install watch

seantomburke
fonte
23
Definitivamente o caminho a percorrer se você usar brewno mac.
Maxence
2
Mais detalhes seriam apreciados. Quando pesquiso "brew watch osx", este é o principal resultado da pesquisa. Edição: Aparentemente, é um comando do Linux. Para aqueles que não tinham certeza de como usar watch: stackoverflow.com/questions/13593771/…
gwg
2
Isso watchdo brew não parece ler os aliases do usuário. Ao executar watch somealias, recebo um comando não encontrado.
RNickMcCandless
O @NickMc, a maneira correta de usar o watch, é watch [command]quando você o usa watch somealias, assumindo que somealiasé um comando que você pode executar no seu terminal.
Seantomburke
38

Use macports :

$ sudo port install watch
GoTLiuM
fonte
3
Não há maneira melhor do que usar o watchcomando diretamente.
Oliver
8
Por que usar o brew em vez do MacPorts?
bmauter
1
@bmauter, para cada um deles: stackoverflow.com/questions/21374366/…
CenterOrbit 2/15
4
@ CenterOrbit, é exatamente por isso que perguntei. @ joseph.hainline diz que não usa MacPorts, mas não indica o porquê. O watchcomando foi preso no MacPorts?
bmauter
Não está preso. Esse é um conselho terrível. MacPorts funciona muito bem e tem toneladas de pacotes. Use-o.
Ali Gangji
16

os shells acima farão o truque, você pode até convertê-los em um alias (talvez seja necessário agrupar uma função para manipular parâmetros)

alias myWatch='_() { while :; do clear; $2; sleep $1; done }; _'

Exemplos:

myWatch 1 ls ## self-explanatory
myWatch 5 "ls -lF $HOME" ## every 5 seconds, list out home dir; double-quotes around command to keep its args together

Como alternativa, a homebrew pode instalar o relógio em http://procps.sourceforge.net/

brew install watch
IT Gumby
fonte
14

Pode ser que "assistir" não seja o que você deseja. Você provavelmente deseja pedir ajuda para resolver seu problema, não para implementar sua solução! :)

Se seu objetivo real é acionar ações com base no que é visto no tailcomando , você pode fazer isso como parte da própria cauda. Em vez de executar "periodicamente", que é o que watchfaz, você pode executar seu código sob demanda .

#!/bin/sh

tail -F /var/log/somelogfile | while read line; do
  if echo "$line" | grep -q '[Ss]ome.regex'; then
    # do your stuff
  fi
done

Observe que tail -Fcontinuará a seguir um arquivo de log, mesmo que ele seja rotacionado pelo newsyslog ou logrotate. Você deseja usar isso em vez de letras minúsculas tail -f. Verifique man tailpara detalhes.

Dito isto, se você realmente deseja executar um comando periodicamente, as outras respostas fornecidas podem ser transformadas em um pequeno script de shell:

#!/bin/sh
if [ -z "$2" ]; then
  echo "Usage: $0 SECONDS COMMAND" >&2
  exit 1
fi

SECONDS=$1
shift 1
while sleep $SECONDS; do
  clear
  $*
done
ghoti
fonte
Infelizmente, este script shell não funciona com parâmetros festança expandida, tais como: relógio 2 gato *
Código Commander
1
@CodeCommander - A linha de comando watch 2 cat *expandia os parâmetros antes de executar o script; portanto, em um diretório com os arquivos "foo" e "bar", você executaria a cat foo barcada 2 segundos. Que comportamento você esperava?
ghoti
@ ghoti Estou apenas apontando que o comportamento é diferente do comando watch no Ubuntu. Aparentemente, a versão do Ubuntu executa o comando a cada dois segundos (expandindo os parâmetros toda vez que é executado), esse script tem os parâmetros expandidos antes de ser executado e, em seguida, é executado usando os mesmos parâmetros a cada dois segundos. Portanto, se você deseja assistir aos arquivos em um diretório em que os arquivos estão sendo adicionados e removidos, esse script não ajuda. É útil quando você não usa parâmetros expandidos. :)
Comandante de código
@ CodeCommander, acho que você está enganado. O Bash (como sh) se expande *sem passar para o comando que você executa. Tente executar: mkdir /tmp/zz; touch /tmp/zz/foo; watch -n 2 ls -l /tmp/zz/*em uma janela. Enquanto estiver em execução, você pode touch /tmp/zz/barem outra janela. Veja se o seu "relógio" vê a alteração, na primeira janela. Eu acho que não. Não é para mim. Isso não tem nada a ver com Ubuntu vs OSX ou Linux vs Unix, é o comportamento em bashsi.
ghoti
1
@hothot, você está certo. Eu estava errado. Mesmo com o comando watch do Linux, você precisa usar aspas: watch "ls -l /tmp/zz/*"mas se você se lembrar de usar aspas, também funciona com o seu script. :)
Comandante de código
10

Indo com a resposta daqui :

bash -c 'while [ 0 ]; do <your command>; sleep 5; done'

Mas é realmente melhor instalar o relógio, pois isso não é muito limpo .

Marvin Pinto
fonte
11
mais fácil agora mesmobrew install watch
Peter Host
6

Se o relógio não quiser instalar via

brew install watch

Existe outra versão semelhante / cópia que foi instalada e funcionou perfeitamente para mim

brew install visionmedia-watch

https://github.com/tj/watch

A_funs
fonte
5

Ou, no seu ~ / .bashrc

function watch {
    while :; do clear; date; echo; $@; sleep 2; done
}
Jon
fonte
2

Eu tive um problema parecido.

Quando pesquisei no Google, me deparei com esse link recentemente. Isso não é exatamente 'instalação de software', simplesmente obter o binário para o comando 'watch'.

E o link é o comando Get watch para OSX

sugavaneshb
fonte
1

Aqui está uma versão ligeiramente alterada desta resposta que:

  • verifica se há argumentos válidos
  • mostra um título de data e duração no topo
  • move o argumento "duration" para ser o primeiro argumento, para que comandos complexos possam ser facilmente transmitidos como os argumentos restantes.

Para usá-lo:

  • Salve isso em ~/bin/watch
  • executar chmod 700 ~/bin/watchem um terminal para torná-lo executável.
  • tente executando watch 1 echo "hi there"

~ / bin / watch

#!/bin/bash

function show_help()
{
  echo ""
  echo "usage: watch [sleep duration in seconds] [command]"
  echo ""
  echo "e.g. To cat a file every second, run the following"
  echo ""
  echo "     watch 1 cat /tmp/it.txt" 
  exit;
}

function show_help_if_required()
{
  if [ "$1" == "help" ]
  then
      show_help
  fi
  if [ -z "$1" ]
    then
      show_help
  fi
}

function require_numeric_value()
{
  REG_EX='^[0-9]+$'
  if ! [[ $1 =~ $REG_EX ]] ; then
    show_help
  fi
}

show_help_if_required $1
require_numeric_value $1

DURATION=$1
shift

while :; do 
  clear
  echo "Updating every $DURATION seconds. Last updated $(date)"
  bash -c "$*"
  sleep $DURATION
done
Brad Parks
fonte
1

Tente o seguinte:

#!/bin/bash
# usage: watch [-n integer] COMMAND

case $# in
    0)
        echo "Usage $0 [-n int] COMMAND"
        ;;
    *)      
        sleep=2;
        ;;
esac    

if [ "$1" == "-n" ]; then
    sleep=$2
    shift; shift
fi


while :; 
    do 
    clear; 
    echo "$(date) every ${sleep}s $@"; echo 
    $@; 
    sleep $sleep; 
done
Robert Nagtegaal
fonte
1

para evitar oscilações quando o comando principal leva um tempo perceptível para ser concluído, você pode capturar a saída e limpar a tela apenas quando terminar.

function watch {while :; do a=$($@); clear; echo "$(date)\n\n$a"; sleep 1; done}

use-o por: watch istats

tungv
fonte
0

Use o gerenciador de pacotes nix !

Instale o nix e, em seguida, nix-env -iA nixpkgs.watchele estará disponível para uso após a conclusão das instruções de instalação (incluindo a fonte . "$HOME/.nix-profile/etc/profile.d/nix.sh"no shell).

galva
fonte