OSX bash,“监视”命令


292

我正在寻找在Mac OSX上复制Linux'watch'命令的最佳方法。我想每隔几秒钟运行一条命令,以使用“ tail”和“ sed”对输出文件的内容进行模式匹配。

在Mac上,我最好的选择是什么,并且无需下载软件就能完成?


2
为什么只安装就想复制它?
安德鲁·马歇尔

3
因为我必须在使用我的脚本的办公室中配置所有Mac
joseph.hainline 2012年

我建议您的脚本先安装brew,然后再观看。
AsTeR 2013年

brew的手表似乎没有拾取我的路径或别名上的命令。
sam boosalis 2014年

除了命令以外,您还可以使用应用程序/Applications/Utilities/Console.app监视日志文件。它允许使用基本搜索进行过滤
JuanMa Cuevas

Answers:


335

您可以使用shell循环模拟基本功能:

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

这将永远循环,清除屏幕,运行命令,并等待两秒钟-基本watch your_command实现。

您可以更进一步,并创建一个watch.sh可以接受your_commandsleep_duration作为参数的脚本:

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

while :; 
  do 
  clear
  date
  $1
  sleep $2
done

2
我相信watch只显示第一屏输出。如果您想做类似的事情,请更改your_commandyour_command 2>&1|head -10
Mark Eirich

10
这很好用,但是我更喜欢sleep ${2:-1}将时间间隔设为可选。
Daniel Lubarov

2
另外,它echo "$(date)"等效于date
Daniel Lubarov 2013年

5
它也不适用于管道。这是经过各种改进的叉子:daniel.lubarov.com/simple-watch-script-for-osx
Daniel Lubarov 2013年

watch与输出超过一个屏幕时不一样。仅显示结尾,而watch仅显示顶部。(都不理想)
h__14年

545

随着家酿安装:

brew install watch


23
如果brew在Mac上使用,绝对是必经之路。
Maxence

2
更多细节将不胜感激。当我搜索“ brew watch osx”时,这是搜索结果的顶部。编辑:显然,这是一个Linux命令。对于那些不确定如何使用的人watch stackoverflow.com/questions/13593771/…–
gwg

2
watch从BREW似乎并没有读取用户的别名。执行时watch somealias,找不到命令。
RNickMcCandless '16

@NickMc使用watch的正确方法是watch [command]在使用watch somealias它时进行操作,假设这somealias是可以在终端中运行的命令。
seantomburke's

38

使用macports

$ sudo port install watch

3
没有比watch直接使用命令更好的方法了。
奥利弗·2013年

8
为什么要使用brew而不是MacPorts?
bmauter 2015年


4
@CenterOrbit,这正是我问的原因。@ joseph.hainline说不使用MacPorts,但没有说明原因。watchMacPorts中的命令是否被破坏?
bmauter

它没有被破坏。那是可怕的建议。MacPorts的工作原理非常好,并且有很多软件包。用它。
阿里Gangji

16

上面的shell可以解决问题,您甚至可以将它们转换为别名(可能需要包装函数来处理参数)

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

例子:

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

或者,自制软件可以从http://procps.sourceforge.net/安装手表

brew install watch

14

可能“监视”不是您想要的。您可能想寻求解决问题的帮助,而不是寻求解决方案的帮助!:)

如果您的真正目标是根据tail命令中看到的内容触发操作,那么您可以将其作为尾巴本身的一部分来执行。watch您可以按需运行您的代码而不是“定期” 运行。

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

请注意,tail -F即使日志文件被newsyslog或logrotate轮换,它将继续跟随日志文件。您要使用它而不是小写字母tail -f。检查man tail详细信息。

也就是说,如果您确实希望定期运行命令,则可以将提供的其他答案转换为简短的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

不幸的是,此shell脚本不适用于bash扩展的参数,例如:watch 2 cat *
Code Commander

1
@CodeCommander-命令行将watch 2 cat *在运行脚本之前扩展参数,因此在包含文件“ foo”和“ bar”的目录中,您将cat foo bar每2秒运行一次。您期望什么行为?
ghoti 2013年

@ghoti我只是指出行为与Ubuntu上的watch命令不同。Ubuntu版本显然每两秒钟运行一次命令(每次运行时都会扩展参数),此脚本在运行前会先扩展参数,然后每两秒使用相同的参数运行。因此,如果要在要添加和删除文件的目录中监视文件,则此脚本无济于事。但是,当您不使用扩展参数时,它很有用。:)
Code Commander

@CodeCommander,我想你错了。Bash(如sh)会扩展,*而不会传递给您运行的命令。尝试mkdir /tmp/zz; touch /tmp/zz/foo; watch -n 2 ls -l /tmp/zz/*在一个窗口中运行:。在运行时,您可以touch /tmp/zz/bar在另一个窗口中。在第一个窗口中查看您的“手表”是否看到更改。我认为不会。不适合我 这与Ubuntu vs OSX或Linux vs Unix无关,这是它bash本身的行为。
ghoti

1
@ghoti,你是对的。我误解了。即使使用Linux watch命令,您也需要使用引号:watch "ls -l /tmp/zz/*"但是,如果您记得使用引号,它也可以与脚本一起使用。:)
指挥官



5

或者,在您的〜/ .bashrc中

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

2

我有一个类似的问题。

当我用谷歌搜索时,我最近发现了这个链接。这不完全是“安装软件”,只是获取“ watch”命令的二进制文件。

链接是OSX的Get watch命令


1

是此答案的略有变化的版本:

  • 检查有效的参数
  • 在顶部显示日期和持续时间标题
  • 将“ duration”参数移动为第一个参数,因此可以轻松地将复杂的命令作为其余参数传递。

要使用它:

  • 保存到 ~/bin/watch
  • chmod 700 ~/bin/watch在终端中执行以使其可执行。
  • 通过运行尝试 watch 1 echo "hi there"

〜/ bin /手表

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

1

尝试这个:

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

1

为了防止在您的主命令花费可察觉的时间完成时闪烁,您可以捕获输出,并且仅在完成后清除屏幕。

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

然后通过以下方式使用它: watch istats


0

使用nix软件包管理器!

然后安装nix,nix-env -iA nixpkgs.watch在完成安装说明(包括从. "$HOME/.nix-profile/etc/profile.d/nix.sh"Shell中采购)后,它应该可以使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.