mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
let exec node take msg.kill SIG... param and pid param
and redo test
This commit is contained in:
parent
4a8a5ed8d4
commit
c6436f47eb
@ -46,22 +46,23 @@
|
|||||||
<script type="text/x-red" data-help-name="exec">
|
<script type="text/x-red" data-help-name="exec">
|
||||||
<p>Calls out to a system command.<br/></p>
|
<p>Calls out to a system command.<br/></p>
|
||||||
<p>Provides 3 outputs: stdout, stderr, and return code.</p>
|
<p>Provides 3 outputs: stdout, stderr, and return code.</p>
|
||||||
<p>By default uses the <code>exec</code> system call which calls the command, then gets a callback
|
<p>By default uses the <code>exec</code> system call which calls the command, waits for it to complete, and
|
||||||
on completion, returning stdout as the payload to the first, the error code as the third
|
returns the normal output to the first port, any error text to the second port, and a return code object to the
|
||||||
and, if available, stderr to the second output. If no error occurred, a zero is returned on the third output.</p>
|
third port. For example a succesful command should return <code>{ code: 0 }</code>.</p>
|
||||||
<p>Optionally can use <code>spawn</code> instead, which returns the output from stdout and stderr
|
<p>Optionally can use <code>spawn</code> instead, which returns the output from stdout and stderr
|
||||||
as the command runs (usually one line at a time). On completion it then returns a return code
|
as the command runs, usually one line at a time. On completion it then returns a numeric return code
|
||||||
(on the 3rd output).</p>
|
on the 3rd port. For example a successful command should return <code>0</code>.</p>
|
||||||
<p>The <code>exec</code> method spawns a subshell and therefore can be used for more complicated
|
<p>The <code>exec</code> method spawns a subshell and therefore can be used for more complicated
|
||||||
commands involving pipes. However, it waits for completion of the whole command before returing anything.</p>
|
commands involving pipes. However, it waits for completion of the whole command before returing anything.</p>
|
||||||
<p>The optional append gets added to the command after <code>msg.payload</code> - so you can do
|
<p>The optional <b>append</b> gets added to the command after <code>msg.payload</code> - so you can do
|
||||||
things like pipe the result to another command.</p>
|
things like pipe the result to another command.</p>
|
||||||
<p>Commands or parameters with spaces should be enclosed in quotes - <i>"This is a single parameter"</i></p>
|
<p>Commands or parameters with spaces should be enclosed in quotes - <i>"This is a single parameter"</i></p>
|
||||||
<p>If stdout is binary a <i>buffer</i> is returned - otherwise returns a <i>string</i>.</p>
|
<p>The <code>payload</code> is usually a <i>string</i>, unless binary is detected, in which case it contains a <i>buffer</i>.</p>
|
||||||
<p>The blue status icon and PID will be visible while the node is active.</p>
|
<p>The blue status icon and PID will be visible while the node is active. This can be read by a <code>status</code> node.</p>
|
||||||
<p>Sending <code>msg.kill</code> will kill a single active process. If there is more than one process running then
|
<p>Sending <code>msg.kill</code> will kill a single active process. <code>msg.kill</code> should be a string containing
|
||||||
<code>msg.kill</code> must be set with the value of the PID to be killed.</p>
|
the type of signal to be sent, e.g. "SIGINT", "SIGQUIT", "SIGHUP", etc. Defaults to "SIGTERM" if blank ("").
|
||||||
<p>Tip: If running a Python app you may need to use the <code>-u</code> parameter to stop the output being buffered.</p>
|
If there is more than one process running then <code>msg.pid</code> must also be set with the value of the PID to be killed.</p>
|
||||||
|
<p><b>Tip: </b>If running a Python app you may need to use the <code>-u</code> parameter to stop the output being buffered.</p>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
@ -78,7 +79,7 @@
|
|||||||
},
|
},
|
||||||
inputs:1,
|
inputs:1,
|
||||||
outputs:3,
|
outputs:3,
|
||||||
outputLabels: ["stdout","stderr","rc"],
|
outputLabels: ["stdout","stderr","return code"],
|
||||||
icon: "arrow-in.png",
|
icon: "arrow-in.png",
|
||||||
align: "right",
|
align: "right",
|
||||||
label: function() {
|
label: function() {
|
||||||
|
@ -39,13 +39,16 @@ module.exports = function(RED) {
|
|||||||
|
|
||||||
this.on("input", function(msg) {
|
this.on("input", function(msg) {
|
||||||
if (msg.hasOwnProperty("kill")) {
|
if (msg.hasOwnProperty("kill")) {
|
||||||
if (node.activeProcesses.hasOwnProperty(msg.kill) ) {
|
if (typeof msg.kill !== "string" || msg.kill.length === 0 || !msg.kill.toUpperCase().startsWith("SIG") ) { msg.kill = ""; }
|
||||||
node.activeProcesses[msg.kill].kill();
|
if (msg.hasOwnProperty("pid")) {
|
||||||
node.status({fill:"red",shape:"dot",text:"killed"});
|
if (node.activeProcesses.hasOwnProperty(msg.pid) ) {
|
||||||
|
node.activeProcesses[msg.pid].kill(msg.kill.toUpperCase());
|
||||||
|
node.status({fill:"red",shape:"dot",text:"killed"});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (Object.keys(node.activeProcesses).length === 1) {
|
if (Object.keys(node.activeProcesses).length === 1) {
|
||||||
node.activeProcesses[Object.keys(node.activeProcesses)[0]].kill();
|
node.activeProcesses[Object.keys(node.activeProcesses)[0]].kill(msg.kill.toUpperCase());
|
||||||
node.status({fill:"red",shape:"dot",text:"killed"});
|
node.status({fill:"red",shape:"dot",text:"killed"});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,7 +152,7 @@ module.exports = function(RED) {
|
|||||||
/* istanbul ignore else */
|
/* istanbul ignore else */
|
||||||
if (node.activeProcesses.hasOwnProperty(pid)) {
|
if (node.activeProcesses.hasOwnProperty(pid)) {
|
||||||
if (node.activeProcesses[pid].tout) { clearTimeout(node.activeProcesses[pid].tout); }
|
if (node.activeProcesses[pid].tout) { clearTimeout(node.activeProcesses[pid].tout); }
|
||||||
// console.log("KILLLING",pid);
|
// console.log("KILLING",pid);
|
||||||
var process = node.activeProcesses[pid];
|
var process = node.activeProcesses[pid];
|
||||||
node.activeProcesses[pid] = null;
|
node.activeProcesses[pid] = null;
|
||||||
process.kill();
|
process.kill();
|
||||||
|
@ -239,7 +239,32 @@ describe('exec node', function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
n1.receive({kill:true});
|
n1.receive({kill:""});
|
||||||
|
},150);
|
||||||
|
n1.receive({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to kill a long running command - SIGINT', function(done) {
|
||||||
|
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2"},
|
||||||
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
|
helper.load(execNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
var n3 = helper.getNode("n3");
|
||||||
|
var n4 = helper.getNode("n4");
|
||||||
|
n4.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.have.property("killed",true);
|
||||||
|
msg.payload.should.have.property("signal","SIGINT");
|
||||||
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setTimeout(function() {
|
||||||
|
n1.receive({kill:"sigint"});
|
||||||
},150);
|
},150);
|
||||||
n1.receive({});
|
n1.receive({});
|
||||||
});
|
});
|
||||||
@ -509,7 +534,28 @@ describe('exec node', function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
n1.receive({kill:true});
|
n1.receive({kill:""});
|
||||||
|
},150);
|
||||||
|
n1.receive({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to kill a long running command - SIGQUIT', function(done) {
|
||||||
|
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2"},
|
||||||
|
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||||
|
helper.load(execNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
var n3 = helper.getNode("n3");
|
||||||
|
var n4 = helper.getNode("n4");
|
||||||
|
n4.on("input", function(msg) {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.have.property("killed",true);
|
||||||
|
msg.payload.should.have.property("signal","SIGQUIT");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
setTimeout(function() {
|
||||||
|
n1.receive({kill:"sigquit"});
|
||||||
},150);
|
},150);
|
||||||
n1.receive({});
|
n1.receive({});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user