entr：文件更改时重新运行构建
文件监控 inotify
![](/data/attachment/album/202007/11/094223uct6386d9iwctmbh.jpg)


这是一篇简短的文章。我是最近才发现 [entr](http://eradman.com/entrproject/) 的，我很惊奇从来没有人告诉过我？！因此，如果你和我一样，那么我告诉你它是什么。


[entr 的网站](http://eradman.com/entrproject/)上对它已经有很好的解释，也有很多示例。


总结在其头部：`entr` 是一个命令行工具，当每次更改一组指定文件中的任何一个时，都能运行一个任意命令。你在标准输入给它传递要监控的文件列表，如下所示：



```
git ls-files | entr bash my-build-script.sh

```

或者



```
find . -name *.rs | entr cargo test

```

或者任何你希望的。


### 快速反馈很棒


就像世界上的每个程序员一样，我发现每次更改代码时都必须手动重新运行构建/测试非常烦人。


许多工具（例如 hugo 和 flask）都有一个内置的系统，可以在更改文件时自动重建，这很棒！


但是通常我会自己编写一些自定义的构建过程（例如 `bash build.sh`），而 `entr` 让我有了一种神奇的构建经验，我只用一行 bash 就能得到即时反馈，知道我的改变是否修复了那个奇怪的 bug。万岁！


### 重启服务器（entr -r）


但是如果你正在运行服务器，并且每次都需要重新启动服务器怎么办？如果你传递 `-r`，那么 `entr` 会帮你的



```
git ls-files | entr -r python my-server.py

```

### 清除屏幕（entr -c）


另一个简洁的标志是 `-c`，它让你可以在重新运行命令之前清除屏幕，以免被前面构建的输出分散注意力。


### 与 git ls-files 一起使用


通常，我要跟踪的文件集和我在 git 中的文件列表大致相同，因此将 `git ls-files` 传递给 `entr` 是很自然的事情。


我现在有一个项目，有时候我刚创建的文件还没有在 git 里。那么如果你想包含未被跟踪的文件怎么办呢？这些 `git` 命令行参数就可以做到（我是从一个读者的邮件中得到的，谢谢你！）：



```
git ls-files -cdmo --exclude-standard  | entr your-build-script

```

有人给我发了邮件，说他们做了一个 `git-entr` 命令，可以执行：



```
git ls-files -cdmo --exclude-standard | entr -d "$@"

```

我觉得这真是一个很棒的主意。


### 每次添加新文件时重启：entr -d


`git ls-files` 的另一个问题是有时候我添加一个新文件，当然它还没有在 git 中。`entr` 为此提供了一个很好的功能。如果你传递 `-d`，那么如果你在 `entr` 跟踪的任何目录中添加新文件，它就会退出。


我将它与一个 `while` 循环配合使用，它将重启 `entr` 来包括新文件，如下所示：



```
while true
do
{ git ls-files; git ls-files . --exclude-standard --others; } | entr -d your-build-scriot
done

```

### entr 在 Linux 上的工作方式：inotify


在 Linux 中，`entr` 使用 `inotify`（用于跟踪文件更改这样的文件系统事件的系统）工作。如果用 `strace` 跟踪它，那么你会看到每个监控文件的 `inotify_add_watch` 系统调用，如下所示：



```
inotify_add_watch(3, "static/stylesheets/screen.css", IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE_SELF|IN_MOVE_SELF) = 1152

```

### 就这样了


我希望这可以帮助一些人了解 `entr`！




---


via: <https://jvns.ca/blog/2020/06/28/entr/>


作者：[Julia Evans](https://jvns.ca/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
This is going to be a pretty quick post – I found out about [ entr](http://eradman.com/entrproject/) relatively
recently and I felt like WHY DID NOBODY TELL ME ABOUT THIS BEFORE?!?! So I’m
telling you about it in case you’re in the same boat as I was.

There’s a great explanation of the tool with lots of examples on [entr’s website](http://eradman.com/entrproject/).

The summary is in the headline: `entr`

is a command line tool that lets you run
an arbitrary command every time you change any of a set of specified files. You
pass it the list of files to watch on stdin, like this:

```
git ls-files | entr bash my-build-script.sh
```


or

```
find . -name *.rs | entr cargo test
```


or whatever you want really.

### quick feedback is amazing

Like possibly every single programmer in the universe, I find it Very Annoying to have to manually rerun my build / tests every time I make a change to my code.

A lot of tools (like hugo and flask) have a built in system to automatically rebuild when you change your files, which is great!

But often I have some hacked together custom build process that I wrote myself
(like `bash build.sh`

), and `entr`

lets me have a magical build experience
where I get instant feedback on whether my change fixed the weird bug with just
one line of bash. Hooray!

### restart a server (`entr -r`

)

Okay, but what if you’re running a server, and the server needs to be restarted
every time you change a file? entr’s got you – if you pass `-r`

, then

```
git ls-files | entr -r python my-server.py
```


### clear the screen (`entr -c`

)

Another neat flag is `-c`

, which lets you clear the screen before rerunning the
command, so that you don’t get distracted/confused by the previous build’s
output.

### use it with `git ls-files`


Usually the set of files I want to track is about the same list of files I have
in git, so `git ls-files`

is a natural thing to pipe to `entr`

.

I have a project right now where sometimes I have files that I’ve just created that aren’t in git just yet. So what if you want to include untracked files? These git command line arguments will do it (I got them from an email from a reader, thank you!):

```
git ls-files -cdmo --exclude-standard | entr your-build-script
```


Someone emailed me and said they have a `git-entr`

command that runs

```
git ls-files -cdmo --exclude-standard | entr -d "$@"
```


which I think is a great idea.

### restart every time a new file is added: `entr -d`


The other problem with this `git ls-files`

thing is that sometimes I add a new
file, and of course it’s not in git yet. entr has a nice feature for this – if
you pass `-d`

, then if you add a new file in any of the directories entr is
tracking, then it’ll exit.

I’m using this paired with a little while loop that will restart
`entr`

to include the new files, like this:

```
while true
do
{ git ls-files; git ls-files . --exclude-standard --others; } | entr -d your-build-script
done
```


### how entr works on Linux: inotify

On Linux, entr works using `inotify`

(a system for tracking filesystem events
like file changes) – if you strace it, you’ll see an `inotify_add_watch`

system call for each file you ask it to watch, like this:

```
inotify_add_watch(3, "static/stylesheets/screen.css", IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE_SELF|IN_MOVE_SELF) = 1152
```


### that’s all!

I hope this helps a few people learn about `entr`

!