基于Bash的热重载实现

时间:2017-02-05 08:30:26

标签: linux bash unit-testing automated-tests git-bash

tl;博士版 问题:如何使bash脚本/命令侦听对文件的更改,然后输出特定Bash命令的结果?

长版 真实场景:我正在重构一个Perl模块( my_module.pm ),我有一个与该模块关联的测试文件( my_module.t )。我想把控制台放在一个屏幕上,每当我保存pm文件时(在另一个屏幕上使用编辑器),控制台就会运行prove -v my_module.t

背景:我拥有当前目录中的所有权限,如果需要,我可以提升到sudo。我不介意实现是否类似于setInterval,因为它仅用于开发目的。只要我有办法clearInterval并且脚本在文件未更改时不会产生永无止境的输出那么它就是好的:)

示例场景: 假设bash脚本名为hot,并且只要更改了给定的文件,它就会运行ls -l source.txt。 因此,当我运行hot source.txt时,脚本可能会或可能不会运行ls ....一次。然后当我修改source.txt时,运行hot的控制台将再次运行ls,我应该会看到source.txt的新文件大小(以及其他信息)。 如果我运行hot something.txt,则修改source.txt时,它不应运行ls。即使未修改source.txt,每当我修改ls时,脚本都会触发something.txt

我想这可以通过while循环实现,但是我很难跟踪文件更改(并且最好跟踪间隔以减少资源占用)。任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

使用inotifywait监视文件以查找更改事件,并对其修改运行测试。

SELECT FAQ_ID, FAQ_Title, Game, Platforms FROM faqlist WHERE FAQ_Title 
LIKE 'General Walkthrough%' 
AND UNION
SELECT FAQ_ID, FAQ_Title, Game, Platforms FROM faqlist WHERE Platforms = '%DS%'
AND UNION
SELECT FAQ_ID, FAQ_Title, Game, Platforms FROM faqlist WHERE Game = 'Metal Slug' 
ORDER BY FAQ_ID ASC;

标志的用法如下。您的案例中的事件inotifywait -q -m -e close_write my_module.pm | while read -r filename event; do prove -v my_module.t done 标记为-e,这意味着该文件在最近打开后才会被关闭。

close_write

答案 1 :(得分:0)

我最终将这个功能提交到我的~/.bashrc

function hot {
  if (( $# < 2 )); then
    echo 'USAGE: hot <command> <file1> [<file2> ... <fileN>]'
    echo '<command> will be run once when any of the files listed is changed (i.e. ls -l <file> has its output changed)'
  else
    script=$1
    shift
    a='';
    while true; do
      b=`ls -l $*`
      [[ $a != $b ]] && a=$b && eval $script;
      sleep .5;
    done
  fi
}

所以我可以hot 'prove my_module.t' my_module.pm,如示例中所述,我也可以hot 'ls -l source.txt' source.txt

实际上,我希望在文件或测试文件更改后运行测试。因此,我会做hot 'prove my_module.t' my_module.pm my_module.t

[[ $a != $b ]] && a=$b && eval $script;行是为了避免让自己与嵌套混淆 - 如果是a=$b; eval $script $a != $b,这是a, b = np.loadtxt("data_.txt", skiprows=1).T 的“简短形式”。

希望这有助于其他人寻找答案。 :)