Add -k option to send SIGKILL instead of SIGTERM; closes #31
This commit is contained in:
parent
787c31040c
commit
9c65e816da
2
Makefile
2
Makefile
|
@ -1,6 +1,6 @@
|
||||||
VER=$(shell grep version Cargo.toml | head -n1 | grep -Eow '".+"' | sed 's/"//g')
|
VER=$(shell grep version Cargo.toml | head -n1 | grep -Eow '".+"' | sed 's/"//g')
|
||||||
|
|
||||||
.PHONY: doc
|
.PHONY: doc test
|
||||||
|
|
||||||
debug: src/* Cargo.toml
|
debug: src/* Cargo.toml
|
||||||
@cargo build
|
@cargo build
|
||||||
|
|
|
@ -54,6 +54,10 @@ Call/restart `python server.py` when any Python file in the current directory (a
|
||||||
|
|
||||||
$ watchexec -e py -r python server.py
|
$ watchexec -e py -r python server.py
|
||||||
|
|
||||||
|
Call/restart `my_server` when any file in the current directory (and all subdirectories) changes, sending `SIGKILL` to stop the child process:
|
||||||
|
|
||||||
|
$ watchexec -r -k my_server
|
||||||
|
|
||||||
Run `make` when any file changes, using the `.gitignore` file in the current directory to filter:
|
Run `make` when any file changes, using the `.gitignore` file in the current directory to filter:
|
||||||
|
|
||||||
$ watchexec make
|
$ watchexec make
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
.\" generated with Ronn/v0.7.3
|
.\" generated with Ronn/v0.7.3
|
||||||
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||||
.
|
.
|
||||||
.TH "WATCHEXEC" "1" "November 2016" "" ""
|
.TH "WATCHEXEC" "1" "December 2016" "" ""
|
||||||
.
|
.
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
\fBwatchexec\fR \- execute commands when watched files change
|
\fBwatchexec\fR \- execute commands when watched files change
|
||||||
|
@ -30,12 +30,16 @@ Comma\-separated list of file extensions to filter by\. Leading dots are allowed
|
||||||
Ignores modifications from paths that do not match \fIpattern\fR\. This option can be specified multiple times, where a match on any given pattern causes the path to trigger \fIcommand\fR\.
|
Ignores modifications from paths that do not match \fIpattern\fR\. This option can be specified multiple times, where a match on any given pattern causes the path to trigger \fIcommand\fR\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-k\fR, \fB\-\-kill\fR
|
||||||
|
Send \fBSIGKILL\fR to the child process group instead of \fBSIGTERM\fR\.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
\fB\-i\fR, \fB\-\-ignore\fR \fIpattern\fR
|
\fB\-i\fR, \fB\-\-ignore\fR \fIpattern\fR
|
||||||
Ignores modifications from paths that match \fIpattern\fR\. This option can be specified multiple times, and a match on any pattern causes the path to be ignored\.
|
Ignores modifications from paths that match \fIpattern\fR\. This option can be specified multiple times, and a match on any pattern causes the path to be ignored\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fB\-r\fR, \fB\-\-restart\fR
|
\fB\-r\fR, \fB\-\-restart\fR
|
||||||
Sends \fBSIGTERM\fR to the child process if it is still running when subsequent file modifications are detected, then waits for the child to exit\.
|
Terminates the child process group if it is still running when subsequent file modifications are detected\. By default, sends \fBSIGTERM\fR; use \fB\-\-kill\fR to send \fBSIGKILL\fR\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fB\-c\fR, \fB\-\-clear\fR
|
\fB\-c\fR, \fB\-\-clear\fR
|
||||||
|
|
|
@ -88,8 +88,9 @@
|
||||||
<dt class="flush"><var>cmd</var></dt><dd><p>Command to run when watched files are modified, and at startup, unless <code>--postpone</code> is specified. All <var>argument</var>s are passed to <var>cmd</var>.</p></dd>
|
<dt class="flush"><var>cmd</var></dt><dd><p>Command to run when watched files are modified, and at startup, unless <code>--postpone</code> is specified. All <var>argument</var>s are passed to <var>cmd</var>.</p></dd>
|
||||||
<dt><code>-e</code>, <code>--exts</code> <var>extensions</var></dt><dd><p>Comma-separated list of file extensions to filter by. Leading dots are allowed (.rs) are allowed. (This is a shorthand for <code>-f</code>).</p></dd>
|
<dt><code>-e</code>, <code>--exts</code> <var>extensions</var></dt><dd><p>Comma-separated list of file extensions to filter by. Leading dots are allowed (.rs) are allowed. (This is a shorthand for <code>-f</code>).</p></dd>
|
||||||
<dt><code>-f</code>, <code>--filter</code> <var>pattern</var></dt><dd><p>Ignores modifications from paths that do not match <var>pattern</var>. This option can be specified multiple times, where a match on any given pattern causes the path to trigger <em>command</em>.</p></dd>
|
<dt><code>-f</code>, <code>--filter</code> <var>pattern</var></dt><dd><p>Ignores modifications from paths that do not match <var>pattern</var>. This option can be specified multiple times, where a match on any given pattern causes the path to trigger <em>command</em>.</p></dd>
|
||||||
|
<dt><code>-k</code>, <code>--kill</code></dt><dd><p>Send <code>SIGKILL</code> to the child process group instead of <code>SIGTERM</code>.</p></dd>
|
||||||
<dt><code>-i</code>, <code>--ignore</code> <em>pattern</em></dt><dd><p>Ignores modifications from paths that match <var>pattern</var>. This option can be specified multiple times, and a match on any pattern causes the path to be ignored.</p></dd>
|
<dt><code>-i</code>, <code>--ignore</code> <em>pattern</em></dt><dd><p>Ignores modifications from paths that match <var>pattern</var>. This option can be specified multiple times, and a match on any pattern causes the path to be ignored.</p></dd>
|
||||||
<dt><code>-r</code>, <code>--restart</code></dt><dd><p>Sends <code>SIGTERM</code> to the child process if it is still running when subsequent file modifications are detected, then waits for the child to exit.</p></dd>
|
<dt><code>-r</code>, <code>--restart</code></dt><dd><p>Terminates the child process group if it is still running when subsequent file modifications are detected. By default, sends <code>SIGTERM</code>; use <code>--kill</code> to send <code>SIGKILL</code>.</p></dd>
|
||||||
<dt><code>-c</code>, <code>--clear</code></dt><dd><p>Clears the screen before executing <var>command</var>.</p></dd>
|
<dt><code>-c</code>, <code>--clear</code></dt><dd><p>Clears the screen before executing <var>command</var>.</p></dd>
|
||||||
<dt><code>-p</code>, <code>--postpone</code></dt><dd><p>Postpone execution of <var>command</var> until the first file modification is detected.</p></dd>
|
<dt><code>-p</code>, <code>--postpone</code></dt><dd><p>Postpone execution of <var>command</var> until the first file modification is detected.</p></dd>
|
||||||
<dt><code>-d</code>, <code>--debug</code></dt><dd><p>Prints diagnostic messages to STDERR</p></dd>
|
<dt><code>-d</code>, <code>--debug</code></dt><dd><p>Prints diagnostic messages to STDERR</p></dd>
|
||||||
|
@ -127,7 +128,7 @@
|
||||||
|
|
||||||
<ol class='man-decor man-foot man foot'>
|
<ol class='man-decor man-foot man foot'>
|
||||||
<li class='tl'></li>
|
<li class='tl'></li>
|
||||||
<li class='tc'>November 2016</li>
|
<li class='tc'>December 2016</li>
|
||||||
<li class='tr'>watchexec(1)</li>
|
<li class='tr'>watchexec(1)</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,14 @@ Comma-separated list of file extensions to filter by. Leading dots are allowed (
|
||||||
* `-f`, `--filter` <pattern>:
|
* `-f`, `--filter` <pattern>:
|
||||||
Ignores modifications from paths that do not match <pattern>. This option can be specified multiple times, where a match on any given pattern causes the path to trigger *command*.
|
Ignores modifications from paths that do not match <pattern>. This option can be specified multiple times, where a match on any given pattern causes the path to trigger *command*.
|
||||||
|
|
||||||
|
* `-k`, `--kill`:
|
||||||
|
Send `SIGKILL` to the child process group instead of `SIGTERM`.
|
||||||
|
|
||||||
* `-i`, `--ignore` *pattern*:
|
* `-i`, `--ignore` *pattern*:
|
||||||
Ignores modifications from paths that match <pattern>. This option can be specified multiple times, and a match on any pattern causes the path to be ignored.
|
Ignores modifications from paths that match <pattern>. This option can be specified multiple times, and a match on any pattern causes the path to be ignored.
|
||||||
|
|
||||||
* `-r`, `--restart`:
|
* `-r`, `--restart`:
|
||||||
Sends `SIGTERM` to the child process if it is still running when subsequent file modifications are detected, then waits for the child to exit.
|
Terminates the child process group if it is still running when subsequent file modifications are detected. By default, sends `SIGTERM`; use `--kill` to send `SIGKILL`.
|
||||||
|
|
||||||
* `-c`, `--clear`:
|
* `-c`, `--clear`:
|
||||||
Clears the screen before executing <command>.
|
Clears the screen before executing <command>.
|
||||||
|
|
|
@ -9,6 +9,7 @@ pub struct Args {
|
||||||
pub filters: Vec<String>,
|
pub filters: Vec<String>,
|
||||||
pub ignores: Vec<String>,
|
pub ignores: Vec<String>,
|
||||||
pub clear_screen: bool,
|
pub clear_screen: bool,
|
||||||
|
pub kill: bool,
|
||||||
pub restart: bool,
|
pub restart: bool,
|
||||||
pub debug: bool,
|
pub debug: bool,
|
||||||
pub run_initially: bool,
|
pub run_initially: bool,
|
||||||
|
@ -81,6 +82,9 @@ pub fn get_args() -> Args {
|
||||||
.help("Forces polling mode")
|
.help("Forces polling mode")
|
||||||
.long("force-poll")
|
.long("force-poll")
|
||||||
.value_name("interval"))
|
.value_name("interval"))
|
||||||
|
.arg(Arg::with_name("kill")
|
||||||
|
.help("Send SIGKILL to child processes")
|
||||||
|
.long("kill"))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let cmd = values_t!(args.values_of("command"), String).unwrap().join(" ");
|
let cmd = values_t!(args.values_of("command"), String).unwrap().join(" ");
|
||||||
|
@ -115,6 +119,7 @@ pub fn get_args() -> Args {
|
||||||
filters: filters,
|
filters: filters,
|
||||||
ignores: ignores,
|
ignores: ignores,
|
||||||
clear_screen: args.is_present("clear"),
|
clear_screen: args.is_present("clear"),
|
||||||
|
kill: args.is_present("kill"),
|
||||||
restart: args.is_present("restart"),
|
restart: args.is_present("restart"),
|
||||||
debug: args.is_present("debug"),
|
debug: args.is_present("debug"),
|
||||||
run_initially: !args.is_present("postpone"),
|
run_initially: !args.is_present("postpone"),
|
||||||
|
|
|
@ -79,8 +79,10 @@ fn init_logger(debug: bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let args = cli::get_args();
|
||||||
let child_process: Arc<RwLock<Option<Process>>> = Arc::new(RwLock::new(None));
|
let child_process: Arc<RwLock<Option<Process>>> = Arc::new(RwLock::new(None));
|
||||||
let weak_child = Arc::downgrade(&child_process);
|
let weak_child = Arc::downgrade(&child_process);
|
||||||
|
let kill = args.kill;
|
||||||
|
|
||||||
signal::install_handler(move |sig: Signal| {
|
signal::install_handler(move |sig: Signal| {
|
||||||
if let Some(lock) = weak_child.upgrade() {
|
if let Some(lock) = weak_child.upgrade() {
|
||||||
|
@ -88,7 +90,12 @@ fn main() {
|
||||||
if let Some(ref child) = *strong {
|
if let Some(ref child) = *strong {
|
||||||
match sig {
|
match sig {
|
||||||
Signal::Terminate => {
|
Signal::Terminate => {
|
||||||
|
if kill {
|
||||||
child.kill();
|
child.kill();
|
||||||
|
} else {
|
||||||
|
child.terminate();
|
||||||
|
}
|
||||||
|
|
||||||
child.wait();
|
child.wait();
|
||||||
},
|
},
|
||||||
Signal::Stop => {
|
Signal::Stop => {
|
||||||
|
@ -102,8 +109,6 @@ fn main() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let args = cli::get_args();
|
|
||||||
|
|
||||||
init_logger(args.debug);
|
init_logger(args.debug);
|
||||||
|
|
||||||
let cwd = env::current_dir()
|
let cwd = env::current_dir()
|
||||||
|
|
|
@ -8,8 +8,7 @@ pub use self::imp::Process;
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
mod imp {
|
mod imp {
|
||||||
use libc::c_int;
|
use libc::*;
|
||||||
use libc::pid_t;
|
|
||||||
use std::io::Result;
|
use std::io::Result;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
@ -20,7 +19,6 @@ mod imp {
|
||||||
|
|
||||||
impl Process {
|
impl Process {
|
||||||
pub fn new(cmd: &str, updated_paths: Vec<PathBuf>) -> Result<Process> {
|
pub fn new(cmd: &str, updated_paths: Vec<PathBuf>) -> Result<Process> {
|
||||||
use libc::exit;
|
|
||||||
use nix::unistd::*;
|
use nix::unistd::*;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -80,27 +78,19 @@ mod imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kill(&self) {
|
pub fn kill(&self) {
|
||||||
use libc::SIGTERM;
|
self.signal(SIGKILL);
|
||||||
|
|
||||||
self.signal(SIGTERM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pause(&self) {
|
pub fn pause(&self) {
|
||||||
use libc::SIGTSTP;
|
|
||||||
|
|
||||||
self.signal(SIGTSTP);
|
self.signal(SIGTSTP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn resume(&self) {
|
pub fn resume(&self) {
|
||||||
use libc::SIGCONT;
|
|
||||||
|
|
||||||
self.signal(SIGCONT);
|
self.signal(SIGCONT);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signal(&self, sig: c_int) {
|
fn signal(&self, sig: c_int) {
|
||||||
use libc::*;
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn killpg(pgrp: pid_t, sig: c_int) -> c_int;
|
fn killpg(pgrp: pid_t, sig: c_int) -> c_int;
|
||||||
}
|
}
|
||||||
|
@ -111,6 +101,10 @@ mod imp {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn terminate(&self) {
|
||||||
|
self.signal(SIGTERM);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn wait(&self) {
|
pub fn wait(&self) {
|
||||||
use nix::sys::wait::waitpid;
|
use nix::sys::wait::waitpid;
|
||||||
|
|
||||||
|
@ -181,9 +175,7 @@ mod imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kill(&self) {
|
pub fn kill(&self) {
|
||||||
unsafe {
|
self.terminate();
|
||||||
let _ = TerminateJobObject(self.job, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pause(&self) {
|
pub fn pause(&self) {
|
||||||
|
@ -192,6 +184,13 @@ mod imp {
|
||||||
pub fn resume(&self) {
|
pub fn resume(&self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn terminate(&self) {
|
||||||
|
unsafe {
|
||||||
|
let _ = TerminateJobObject(self.job, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn wait(&self) {
|
pub fn wait(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _ = WaitForSingleObject(self.job, INFINITE);
|
let _ = WaitForSingleObject(self.job, INFINITE);
|
||||||
|
|
Loading…
Reference in New Issue