OS X Bash,“watch”命令

442

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

在Mac上,我的最佳选择是什么?是否可以在不下载软件的情况下完成?


3
因为我需要配置办公室所有使用我的脚本的Mac电脑。 - joseph.hainline
Brew 的 watch 命令好像无法识别我路径或别名上的命令。 - sam boosalis
除了使用命令之外,您还可以使用应用程序/Applications/Utilities/Console.app来监视日志文件。它允许使用基本搜索进行过滤。 - JuanMa Cuevas
这个问题不应该发在http://apple.stackexchange.com吗? - igauravsehrawat
你可以使用像brew这样的包管理器。 - Secko
Brew 的 watch 不支持 Unicode :/ - Hakanai
14个回答

848

安装了Homebrew后:

brew install watch

43
如果你在Mac上使用brew的话,这绝对是正确的做法。 - Maxence
4
请提供更多细节。当我搜索“brew watch osx”时,这是排名最高的搜索结果。编辑:显然这是一个Linux命令。对于那些不确定如何使用watch的人,请参考以下链接:https://dev59.com/z2Yr5IYBdhLWcg3wi6vd - jds
6
来自 Brew 的这个 watch 指令似乎无法读取用户别名。当我执行 watch somealias 时,会显示“找不到命令”的错误提示。 - RNickMcCandless
2
@NickMc 使用 watch 的正确方式是执行 watch [command]。当你使用 watch somealias 时,它会假定 somealias 是你可以在终端中运行的命令。 - seantomburke
4
这个回答和被采纳的回答都很好。如果你在安装后运行 man watch,你会发现它比一个简单的命令/脚本具有更多的功能,从默认持续时间和可选开关 (-n) 开始。如果避免依赖是首要任务,那么被采纳的答案非常好,但是否则 brew install watch 需要很少的努力,并且可以给你在使用 Linux 时可能习惯的功能。 - fazy
显示剩余3条评论

442
你可以使用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

3
我认为该命令只会显示第一屏的输出内容。如果您想执行类似操作,将your_command更改为your_command 2>&1|head -10 - Mark Eirich
13
这个方法效果不错,但我更喜欢使用 sleep ${2:-1} 来使时间间隔变成可选的。 - Daniel Lubarov
3
echo "$(date)"date 两者是等价的吗? - Daniel Lubarov
5
它也不能与管道一起使用。这是一个包含各种改进的分叉版本:http://daniel.lubarov.com/simple-watch-script-for-osx - Daniel Lubarov
当输出超过一个屏幕时,其表现不像watch。只显示结尾,而watch则只显示顶部。(两者都不理想) - h__
显示剩余6条评论

44

使用MacPorts

$ sudo port install watch

3
直接使用 watch 命令是最好的方式。 - Oliver
11
为什么使用Brew而不是MacPorts? - bmauter
2
@bmauter,每个人有自己的选择:https://dev59.com/i2Ei5IYBdhLWcg3wWLES - CenterOrbit
5
@CenterOrbit,这正是我问的原因。@joseph.hainline说不要使用MacPorts,但没有说明原因。在MacPorts中,“watch”命令是否失效? - bmauter
1
它没有崩溃。那是可怕的建议。MacPorts运行良好并且有大量软件包。使用它。 - Ali Gangji
5
我从使用MacPorts后,情感上从未恢复过来。这最终彻底损坏了我的系统,以至于我不得不完全重新格式化硬盘。Homebrew无疑是更好的选择 - 我向你挑战,试着找出在ports上很常见但在HB上没有的东西。 - mpowered

22

上面的代码片段足以解决问题,你甚至可以将它们转换为别名(可能需要将其包装在一个函数中以处理参数):

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 directory; double-quotes around command to keep its arguments together

或者,Homebrew可以从http://procps.sourceforge.net/安装watch命令:

brew install watch

1
如果你最终还是要将别名包装在函数中,为什么你更喜欢使用别名而不是函数? - philraj
1
没有特别的偏好,我只是有一个创建别名的习惯。可能这些习惯源于旧的 shell 不依赖或不支持函数,但我无法确认。 - IT Gumby

17

也许 "watch" 不是你想要的。你可能想要寻求帮助解决问题,而不是只实现解决方案! :)

如果你的真正目标是根据从 "tail" 命令中看到的内容触发操作,那么可以将其作为 "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" 的目录中,您将每2秒运行 cat foo bar。 您期望的行为是什么? - ghoti
@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。看看你的“watch”是否在第一个窗口中看到了变化。我不认为会。对我来说也是如此。这与Ubuntu vs OSX或Linux vs Unix无关,而是bash本身的行为。 - ghoti
1
@ghoti,你是对的。我错了。即使使用Linux的watch命令,你也需要使用引号:watch "ls -l /tmp/zz/*"但是如果你记得使用引号,它也可以与你的脚本一起工作。 :) - Code Commander

12

我将采用这里的答案:

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

但是你最好安装watch命令,因为这种方法不太干净...


14
现在更容易了,甚至可以通过“brew install watch”进行安装。 - Peter Host

10

如果无法通过安装程序安装 Watch:

brew install watch

我安装了另一个类似/复制版本,它对我来说完美地安装和运行。

brew install visionmedia-watch

https://github.com/tj/watch


点赞 visionmedia-watch - 它默认支持颜色。watch 不支持,无论是否使用 --color 选项。 - Pavel Haluza

9

或者,在你的~/.bashrc文件中:

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

6
为了防止主要命令执行时间较长时出现闪烁,您可以捕获输出,并在完成时才清除屏幕。
function watch {while :; do a=$($@); clear; echo "$(date)\n\n$a"; sleep 1;  done}

然后通过以下方式使用:

watch istats

应该使用echo -e而不是仅使用echo,以正确呈现这些换行符。 - jez
感谢你们两位,这是一个非常好的答案,适用于限制像Brew这样的软件包管理器安装的客户端机器。 - Brian Topping
实际上,您可以通过执行命令,然后执行“date”并捕获该输出,然后再清除...来进一步减少闪烁。 - Brian Agnew

2

试试这个:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接