【问题标题】:OS X Bash, 'watch' commandOS X Bash,“监视”命令
【发布时间】:2012-03-23 08:44:22
【问题描述】:

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

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

【问题讨论】:

  • 因为我必须配置办公室中使用我的脚本的所有 Mac
  • brew 的手表似乎没有接收到我的路径或别名上的命令。
  • 除了命令之外,您还可以使用应用程序 /Applications/Utilities/Console.app 来监视日志文件。它允许使用基本搜索进行过滤
  • 这不属于apple.stackexchange.com吗?
  • 你可以使用像brew这样的包管理器。

标签: macos bash automation watch


【解决方案1】:

安装了Homebrew

brew install watch

【讨论】:

  • 如果你在 mac 上使用 brew 绝对是正确的选择。
  • 更多细节将不胜感激。当我搜索“brew watch osx”时,这是最高搜索结果。 编辑:显然这是一个 Linux 命令。对于那些不确定如何使用watch的人: stackoverflow.com/questions/13593771/…
  • 这个来自 brew 的 watch 似乎没有读取用户别名。在执行watch somealias 时,我得到一个找不到命令。
  • @NickMc 使用 watch 的正确方法是在使用 watch somealias 时执行 watch [command] 假设 somealias 是可以在终端中运行的命令。
  • 鉴于已接受答案的简单性,在我看来,您的答案是 1. 过分杀伤力 2. 隐藏细节实现,让其他人认为 watch 命令非常难以实现。
【解决方案2】:

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

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

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

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

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

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

【讨论】:

  • 我相信手表只显示第一屏输出。如果您想做类似的事情,请将your_command 更改为your_command 2&gt;&amp;1|head -10
  • 这很好用,但我更喜欢sleep ${2:-1} 使间隔可选。
  • 另外,它的echo "$(date)" 等同于date?
  • 它也不适用于管道。这是一个有各种改进的分叉:daniel.lubarov.com/simple-watch-script-for-osx
  • 当输出超过一屏时不像watch那样工作。仅显示结尾,而watch 仅显示顶部。 (都不理想)
【解决方案3】:

使用MacPorts:

$ sudo port install watch

【讨论】:

  • 没有比直接使用watch 命令更好的方法了。
  • 为什么使用 brew 而不是 MacPorts?
  • @bmauter,每个人都有自己的:stackoverflow.com/questions/21374366/…
  • @CenterOrbit,这正是我问的原因。 @joseph.hainline 说不要使用 MacPorts,但没有说明原因。 watch 命令在 MacPorts 中被破坏了吗?
  • 我从来没有从使用 MacPorts 中恢复过来。它最终彻底搞砸了我的系统,以至于我不得不完全重新格式化我的硬盘驱动器。一路自制——我挑战你找到一些流行的东西,这些东西在 HB 上没有的端口上。
【解决方案4】:

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

或者,Homebrew 可以从http://procps.sourceforge.net/ 安装手表:

brew install watch

【讨论】:

  • 如果你将别名包装在一个函数中,为什么你更喜欢函数?
  • 没有故意的偏好;我只是有创建别名的习惯。这些习惯可能源于不依赖或不支持功能的遗留 shell,但我无法确认。
【解决方案5】:

可能“看”不是你想要的。您可能想寻求帮助以解决您的问题,而不是实施您的解决方案! :)

如果您的真正目标是根据从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 *
  • @CodeCommander - 命令行 watch 2 cat * 会在运行脚本之前扩展参数,因此在包含文件“foo”和“bar”的目录中,您将每 2 秒运行一次 cat foo bar。你期待什么行为?
  • @ghoti 我只是指出该行为与 Ubuntu 上的 watch 命令不同。 Ubuntu版本显然每两秒运行一次命令(每次运行时扩展参数),这个脚本在运行之前扩展了参数,然后每两秒使用相同的参数运行。因此,如果您想查看正在添加和删除文件的目录中的文件,则此脚本无济于事。但是,当您不使用扩展参数时,它很有用。 :)
  • @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,你是对的。我误解了。即使使用 Linux watch 命令,您也需要使用引号:watch "ls -l /tmp/zz/*" 但如果您记得使用引号,它也适用于您的脚本。 :)
【解决方案6】:

我将接受here的回答:

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

但是installing watch 你真的会更好,因为这不是很干净...

【讨论】:

  • 现在更容易了,即使brew install watch
【解决方案7】:

如果手表不想通过安装

brew install watch

还有另一个类似/复制版本对我来说安装和工作得很好

brew install visionmedia-watch

https://github.com/tj/watch

【讨论】:

  • 支持visionmedia-watch - 它默认支持颜色。 watch 没有,有或没有 --color 选项。
【解决方案8】:

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

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

【讨论】:

    【解决方案9】:

    为防止在您的主命令需要可感知的时间才能完成时闪烁,您可以捕获输出并仅在完成后清除屏幕。

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

    然后使用它:

    watch istats
    

    【讨论】:

    • 应该是echo -e 而不仅仅是echo,才能正确呈现这些换行符
    • 感谢你们,对于限制安装包管理器(如 Brew)的客户端计算机,这是一个很好的答案。
    • 事实上你可以通过执行你的命令来进一步减少闪烁,然后执行'date'并捕获那个o/p,然后然后清除......
    【解决方案10】:

    试试这个:

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

    【讨论】:

      【解决方案11】:

      这是一个稍有改动的版本of this answer

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

      使用它:

      • 将此保存到~/bin/watch
      • 在终端中执行chmod 700 ~/bin/watch 使其可执行。
      • 通过运行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
      

      【讨论】:

        【解决方案12】:

        使用Nix 包管理器!

        安装 Nix,然后执行 nix-env -iA nixpkgs.watch,在完成安装说明(包括在您的 shell 中获取 . "$HOME/.nix-profile/etc/profile.d/nix.sh")后,它应该可以使用了。

        【讨论】:

          猜你喜欢
          • 2020-04-13
          • 2015-09-09
          • 1970-01-01
          • 2014-07-05
          • 2016-02-20
          • 1970-01-01
          • 2011-09-22
          • 2013-11-10
          • 1970-01-01
          相关资源
          最近更新 更多