1 | # spawn-rx: A better version of spawn
|
2 |
|
3 | | Linux/OSX | Windows |
|
4 | | --- | --- |
|
5 | | [![Build Status](https://travis-ci.org/tools-rx/spawn-rx.svg?branch=master)](https://travis-ci.org/tools-rx/spawn-rx) | [![Build status](https://ci.appveyor.com/api/projects/status/xm9xpgma4jwy3xns?svg=true)](https://ci.appveyor.com/project/dfbaskin/spawn-rx) |
|
6 |
|
7 | `spawn-rx` is a package that adds an Observable as well as a Promise version of
|
8 | the `child_process.spawn` API, and fixes some deficiencies in `spawn` that come
|
9 | up especially on Windows. For example:
|
10 |
|
11 | * `spawn` searches PATH on POSIX platforms but will not on Windows, you need to
|
12 | provide an exact path. spawn-rx makes Windows act like other platforms.
|
13 |
|
14 | * On Windows, `{detached: true}` doesn't actually create a process group properly.
|
15 | `spawn-rx` provides a `spawnDetached` method that allows you to spawn a detached
|
16 | process and kill the entire process group if needed.
|
17 |
|
18 | * POSIX platforms allow you to directly execute scripts that have a shebang at
|
19 | the top of the file, whereas Windows can only natively `spawn` EXE files, which
|
20 | makes executing npm binaries annoying. `spawn-rx` automatically rewrites your
|
21 | `cmd` and `args` parameters for CMD scripts, PowerShell scripts, and node.js
|
22 | files.
|
23 |
|
24 | ## Examples
|
25 |
|
26 | spawn-as-promise:
|
27 |
|
28 | ```js
|
29 | // Will run down path to find C:\Windows\System32\wmic.exe, whereas normal
|
30 | // 'spawn' would require an absolute path.
|
31 | spawnPromise('wmic', [])
|
32 | .then((result) => console.log(result));
|
33 | ```
|
34 |
|
35 | Handle failed processes as errors:
|
36 |
|
37 | ```js
|
38 | try {
|
39 | await spawnPromise('exit', ['-1']);
|
40 | } catch (e) {
|
41 | console.log("Processes that return non-zero exit codes throw")
|
42 | }
|
43 | ```
|
44 |
|
45 | Kill running process trees:
|
46 |
|
47 | ```js
|
48 | let disp = spawnDetached('takesALongTime', []).subscribe();
|
49 | await Promise.delay(1000);
|
50 |
|
51 | // Kill the process and its children by unsubscribing.
|
52 | disp.dispose();
|
53 | ```
|
54 |
|
55 | Stream process output:
|
56 |
|
57 | ```js
|
58 | spawn('ls', ['-r'])
|
59 | .subscribe(
|
60 | (x) => console.log(x),
|
61 | (e) => console.log("Process exited with an error"));
|
62 | ```
|
63 |
|
64 | Execute scripts:
|
65 |
|
66 | ```js
|
67 | // Executes ./node_modules/.bin/uuid.cmd on Windows if invoked via `npm run`
|
68 | let result = await spawnPromise('uuid');
|
69 | ```
|
70 |
|
71 |
|
72 | ## What's Jobber?
|
73 |
|
74 | Jobber is a Windows executable that will execute a command in a process group,
|
75 | and if signaled via a named pipe, will terminate that process group. It's used
|
76 | in the implementation of `spawnDetached`.
|
77 |
|
78 | ## Spawn output
|
79 |
|
80 | By default spawn will merge stdout and stderr into the returned observable.
|
81 | You can exclude one or the other by passing `ignore` in the `stdio` option of spawn.
|
82 |
|
83 | Alternatively if you call it with `{ split: true }` option, the observable output
|
84 | will be an object `{ source: 'stdout', text: '...' }` so you can distinguish
|
85 | the outputs.
|
86 |
|
87 | ## Stdin support
|
88 |
|
89 | If you provide an `observable<string>` in `opts.stdin`, it'll be subscribed upon
|
90 | and fed into the child process stdin. Its completion will terminate stdin stream.
|
91 |
|
92 | ## Methods
|
93 |
|
94 | ```js
|
95 | /**
|
96 | * Spawns a process attached as a child of the current process.
|
97 | *
|
98 | * @param {string} exe The executable to run
|
99 | * @param {Array<string>} params The parameters to pass to the child
|
100 | * @param {Object} opts Options to pass to spawn.
|
101 | *
|
102 | * @return {Observable<string>} Returns an Observable that when subscribed
|
103 | * to, will create a child process. The
|
104 | * process output will be streamed to this
|
105 | * Observable, and if unsubscribed from, the
|
106 | * process will be terminated early. If the
|
107 | * process terminates with a non-zero value,
|
108 | * the Observable will terminate with onError.
|
109 | */
|
110 | function spawn(exe, params=[], opts=null)
|
111 | ```
|
112 |
|
113 | ```js
|
114 | /**
|
115 | * Spawns a process but detached from the current process. The process is put
|
116 | * into its own Process Group that can be killed by unsubscribing from the
|
117 | * return Observable.
|
118 | *
|
119 | * @param {string} exe The executable to run
|
120 | * @param {Array<string>} params The parameters to pass to the child
|
121 | * @param {Object} opts Options to pass to spawn.
|
122 | *
|
123 | * @return {Observable<string>} Returns an Observable that when subscribed
|
124 | * to, will create a detached process. The
|
125 | * process output will be streamed to this
|
126 | * Observable, and if unsubscribed from, the
|
127 | * process will be terminated early. If the
|
128 | * process terminates with a non-zero value,
|
129 | * the Observable will terminate with onError.
|
130 | */
|
131 | function spawnDetached(exe, params, opts=null)
|
132 | ```
|
133 |
|
134 | ```js
|
135 | /**
|
136 | * Spawns a process as a child process.
|
137 | *
|
138 | * @param {string} exe The executable to run
|
139 | * @param {Array<string>} params The parameters to pass to the child
|
140 | * @param {Object} opts Options to pass to spawn.
|
141 | *
|
142 | * @return {Promise<string>} Returns an Promise that represents a child
|
143 | * process. The value returned is the process
|
144 | * output. If the process terminates with a
|
145 | * non-zero value, the Promise will resolve with
|
146 | * an Error.
|
147 | */
|
148 | function spawnPromise(exe, params, opts=null)
|
149 | ```
|
150 |
|
151 | ```js
|
152 | /**
|
153 | * Spawns a process but detached from the current process. The process is put
|
154 | * into its own Process Group.
|
155 | *
|
156 | * @param {string} exe The executable to run
|
157 | * @param {Array<string>} params The parameters to pass to the child
|
158 | * @param {Object} opts Options to pass to spawn.
|
159 | *
|
160 | * @return {Promise<string>} Returns an Promise that represents a detached
|
161 | * process. The value returned is the process
|
162 | * output. If the process terminates with a
|
163 | * non-zero value, the Promise will resolve with
|
164 | * an Error.
|
165 | */
|
166 | function spawnDetachedPromise(exe, params, opts=null)
|
167 | ```
|
168 |
|
169 | ```js
|
170 | /**
|
171 | * Finds the actual executable and parameters to run on Windows. This method
|
172 | * mimics the POSIX behavior of being able to run scripts as executables by
|
173 | * replacing the passed-in executable with the script runner, for PowerShell,
|
174 | * CMD, and node scripts.
|
175 | *
|
176 | * This method also does the work of running down PATH, which spawn on Windows
|
177 | * also doesn't do, unlike on POSIX.
|
178 | *
|
179 | * @param {string} exe The executable to run
|
180 | * @param {Array<string>} args The arguments to run
|
181 | *
|
182 | * @return {Object} The cmd and args to run
|
183 | * @property {string} cmd The command to pass to spawn
|
184 | * @property {Array<string>} args The arguments to pass to spawn
|
185 | */
|
186 | function findActualExecutable(exe, args)
|
187 | ```
|