From 740ca602821bd92aadf060be961380167776681f Mon Sep 17 00:00:00 2001 From: Mattia Lecci Date: Tue, 15 Apr 2025 16:09:20 +0200 Subject: [PATCH 1/7] Add create/kill background process --- .../SshBackgroundCommandStep.cs | 52 ++++++++++++++ .../SshKillBackgroundCommandStep.cs | 72 +++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 OpenTap.Plugins.Ssh/SshBackgroundCommandStep.cs create mode 100644 OpenTap.Plugins.Ssh/SshKillBackgroundCommandStep.cs diff --git a/OpenTap.Plugins.Ssh/SshBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/SshBackgroundCommandStep.cs new file mode 100644 index 0000000..6c1add5 --- /dev/null +++ b/OpenTap.Plugins.Ssh/SshBackgroundCommandStep.cs @@ -0,0 +1,52 @@ +//Copyright 2019-2020 Keysight Technologies +// +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.ComponentModel; +using Renci.SshNet; + +namespace OpenTap.Plugins.Ssh +{ + + [Display("Background SSH Command", "Run a command in the background using a session setup by an SSH Session step, SSH Instrument or SSH Dut.", Groups: new[] { "SSH", "Background" })] + public class BackgroundSshCommandStep : SshStepBase + { + #region Settings + public string Command { get; set; } + + [Output] + [Display("Process PID", Description:"The PID of the background process", Group: "Response")] + public string pid { get; private set; } + + #endregion + + public BackgroundSshCommandStep() + { + Name = "Background SSH Command {Command}"; + Command = "sleep 10"; + } + + public override void Run() + { + // nohup allows the command to run even when the SSH session ends + // output is suppressed + // the PID of the last background process '$!' is printed to output + SshCommand command = SshResource.SshClient.CreateCommand($"nohup {Command} > /dev/null 2>&1 & echo $!"); + pid = command.Execute(); + + } + } +} diff --git a/OpenTap.Plugins.Ssh/SshKillBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/SshKillBackgroundCommandStep.cs new file mode 100644 index 0000000..d3a65a5 --- /dev/null +++ b/OpenTap.Plugins.Ssh/SshKillBackgroundCommandStep.cs @@ -0,0 +1,72 @@ +//Copyright 2019-2020 Keysight Technologies +// +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.ComponentModel; +using Renci.SshNet; + +namespace OpenTap.Plugins.Ssh +{ + + [Display("Kill Background SSH Command", "Kills a command running in the background.", Groups: new[] { "SSH", "Background" })] + public class KillBackgroundSshCommandStep : SshStepBase + { + #region Settings + [Display("Process PID", "Select the Background SSH Command to kill")] + + public Input InputPid { get; set; } + + #endregion + + public KillBackgroundSshCommandStep() + { + Name = "Kill Background SSH process PID {Process PID}"; + InputPid = new Input(); + } + + public override void Run() + { + if (InputPid == null) + { + throw new ArgumentNullException("No PID was set"); + } + string pid = InputPid.Value; + + SshCommand command = SshResource.SshClient.CreateCommand($"kill {pid}"); + command.Execute(); + + if (command.ExitStatus == 0) + { + Log.Debug($"Gracefully killed PID={pid}"); + UpgradeVerdict(Verdict.Pass); + return; + } + + command = SshResource.SshClient.CreateCommand($"kill -9 {pid}"); + command.Execute(); + + if (command.ExitStatus == 0) + { + Log.Debug($"SIGKILLed PID={pid}"); + UpgradeVerdict(Verdict.Pass); + return; + } + + UpgradeVerdict(Verdict.Fail); + + } + } +} From b9e2701c5658aa815d7d79ec587c53b7d3c6f00d Mon Sep 17 00:00:00 2001 From: Mattia Lecci Date: Tue, 15 Apr 2025 16:25:47 +0200 Subject: [PATCH 2/7] Improve interface and logging --- OpenTap.Plugins.Ssh/SshBackgroundCommandStep.cs | 5 +++-- OpenTap.Plugins.Ssh/SshKillBackgroundCommandStep.cs | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/OpenTap.Plugins.Ssh/SshBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/SshBackgroundCommandStep.cs index 6c1add5..af54334 100644 --- a/OpenTap.Plugins.Ssh/SshBackgroundCommandStep.cs +++ b/OpenTap.Plugins.Ssh/SshBackgroundCommandStep.cs @@ -35,8 +35,7 @@ public class BackgroundSshCommandStep : SshStepBase public BackgroundSshCommandStep() { - Name = "Background SSH Command {Command}"; - Command = "sleep 10"; + Name = "Background SSH Command: {Command}"; } public override void Run() @@ -47,6 +46,8 @@ public override void Run() SshCommand command = SshResource.SshClient.CreateCommand($"nohup {Command} > /dev/null 2>&1 & echo $!"); pid = command.Execute(); + Log.Debug("Running full command: " + command.CommandText); + Log.Info($"Running command `{Command}` in the background"); } } } diff --git a/OpenTap.Plugins.Ssh/SshKillBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/SshKillBackgroundCommandStep.cs index d3a65a5..21ddb1c 100644 --- a/OpenTap.Plugins.Ssh/SshKillBackgroundCommandStep.cs +++ b/OpenTap.Plugins.Ssh/SshKillBackgroundCommandStep.cs @@ -33,7 +33,7 @@ public class KillBackgroundSshCommandStep : SshStepBase public KillBackgroundSshCommandStep() { - Name = "Kill Background SSH process PID {Process PID}"; + Name = "Kill Background SSH Command: PID={Process PID}"; InputPid = new Input(); } @@ -65,8 +65,8 @@ public override void Run() return; } + Log.Error($"Failed killing PID={pid}"); UpgradeVerdict(Verdict.Fail); - } } } From 0447e84cc4b9153bb15ce2df87d503a8d4bccfd2 Mon Sep 17 00:00:00 2001 From: Mattia Lecci Date: Tue, 15 Apr 2025 16:45:32 +0200 Subject: [PATCH 3/7] Add check if background process is still alive --- .../SshCheckBackgroundCommandStep.cs | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 OpenTap.Plugins.Ssh/SshCheckBackgroundCommandStep.cs diff --git a/OpenTap.Plugins.Ssh/SshCheckBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/SshCheckBackgroundCommandStep.cs new file mode 100644 index 0000000..368be5b --- /dev/null +++ b/OpenTap.Plugins.Ssh/SshCheckBackgroundCommandStep.cs @@ -0,0 +1,62 @@ +//Copyright 2019-2020 Keysight Technologies +// +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.ComponentModel; +using Renci.SshNet; + +namespace OpenTap.Plugins.Ssh +{ + + [Display("Check Background SSH Command", "Checks if a background command is still running.", Groups: new[] { "SSH", "Background" })] + public class CheckBackgroundSshCommandStep : SshStepBase + { + #region Settings + [Display("Process PID", "Select the Background SSH Command to kill")] + + public Input InputPid { get; set; } + + #endregion + + public CheckBackgroundSshCommandStep() + { + Name = "Check Background SSH Command: PID={Process PID}"; + InputPid = new Input(); + } + + public override void Run() + { + if (InputPid == null) + { + throw new ArgumentNullException("No PID was set"); + } + string pid = InputPid.Value; + + SshCommand command = SshResource.SshClient.CreateCommand($"ps -p {pid}"); + command.Execute(); + + if (command.ExitStatus == 0) + { + Log.Info($"Process with PID={pid} is alive"); + UpgradeVerdict(Verdict.Pass); + return; + } + + Log.Info($"Process with PID={pid} is not alive"); + UpgradeVerdict(Verdict.Fail); + } + } +} From 1394f1fffc83821989bd02fe280b5f3aed019a48 Mon Sep 17 00:00:00 2001 From: Mattia Lecci Date: Wed, 16 Apr 2025 17:49:39 +0200 Subject: [PATCH 4/7] Add Pid class to better handle Input/Output PIDs --- OpenTap.Plugins.Ssh/Background/Pid.cs | 47 +++++++++++++++++++ .../SshBackgroundCommandStep.cs | 7 +-- .../SshCheckBackgroundCommandStep.cs | 8 ++-- .../SshKillBackgroundCommandStep.cs | 8 ++-- 4 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 OpenTap.Plugins.Ssh/Background/Pid.cs rename OpenTap.Plugins.Ssh/{ => Background}/SshBackgroundCommandStep.cs (91%) rename OpenTap.Plugins.Ssh/{ => Background}/SshCheckBackgroundCommandStep.cs (91%) rename OpenTap.Plugins.Ssh/{ => Background}/SshKillBackgroundCommandStep.cs (92%) diff --git a/OpenTap.Plugins.Ssh/Background/Pid.cs b/OpenTap.Plugins.Ssh/Background/Pid.cs new file mode 100644 index 0000000..2cdd42b --- /dev/null +++ b/OpenTap.Plugins.Ssh/Background/Pid.cs @@ -0,0 +1,47 @@ +//Copyright 2019-2020 Keysight Technologies +// +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.ComponentModel; +using Renci.SshNet; + +namespace OpenTap.Plugins.Ssh +{ + + public class Pid + { + #region Settings + public uint pid { get; private set; } + + #endregion + + public Pid(uint pid) + { + this.pid = pid; + } + + public Pid(string pid) + { + this.pid = uint.Parse(pid); + } + + public override string ToString() + { + return pid.ToString(); + } + + } +} diff --git a/OpenTap.Plugins.Ssh/SshBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/Background/SshBackgroundCommandStep.cs similarity index 91% rename from OpenTap.Plugins.Ssh/SshBackgroundCommandStep.cs rename to OpenTap.Plugins.Ssh/Background/SshBackgroundCommandStep.cs index af54334..4c4d25c 100644 --- a/OpenTap.Plugins.Ssh/SshBackgroundCommandStep.cs +++ b/OpenTap.Plugins.Ssh/Background/SshBackgroundCommandStep.cs @@ -18,7 +18,7 @@ using System.ComponentModel; using Renci.SshNet; -namespace OpenTap.Plugins.Ssh +namespace OpenTap.Plugins.Ssh.Background { [Display("Background SSH Command", "Run a command in the background using a session setup by an SSH Session step, SSH Instrument or SSH Dut.", Groups: new[] { "SSH", "Background" })] @@ -29,7 +29,7 @@ public class BackgroundSshCommandStep : SshStepBase [Output] [Display("Process PID", Description:"The PID of the background process", Group: "Response")] - public string pid { get; private set; } + public Pid pid { get; private set; } #endregion @@ -44,7 +44,8 @@ public override void Run() // output is suppressed // the PID of the last background process '$!' is printed to output SshCommand command = SshResource.SshClient.CreateCommand($"nohup {Command} > /dev/null 2>&1 & echo $!"); - pid = command.Execute(); + string output = command.Execute(); + pid = new Pid(output); Log.Debug("Running full command: " + command.CommandText); Log.Info($"Running command `{Command}` in the background"); diff --git a/OpenTap.Plugins.Ssh/SshCheckBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/Background/SshCheckBackgroundCommandStep.cs similarity index 91% rename from OpenTap.Plugins.Ssh/SshCheckBackgroundCommandStep.cs rename to OpenTap.Plugins.Ssh/Background/SshCheckBackgroundCommandStep.cs index 368be5b..adde0a3 100644 --- a/OpenTap.Plugins.Ssh/SshCheckBackgroundCommandStep.cs +++ b/OpenTap.Plugins.Ssh/Background/SshCheckBackgroundCommandStep.cs @@ -18,7 +18,7 @@ using System.ComponentModel; using Renci.SshNet; -namespace OpenTap.Plugins.Ssh +namespace OpenTap.Plugins.Ssh.Background { [Display("Check Background SSH Command", "Checks if a background command is still running.", Groups: new[] { "SSH", "Background" })] @@ -27,14 +27,14 @@ public class CheckBackgroundSshCommandStep : SshStepBase #region Settings [Display("Process PID", "Select the Background SSH Command to kill")] - public Input InputPid { get; set; } + public Input InputPid { get; set; } #endregion public CheckBackgroundSshCommandStep() { Name = "Check Background SSH Command: PID={Process PID}"; - InputPid = new Input(); + InputPid = new Input(); } public override void Run() @@ -43,7 +43,7 @@ public override void Run() { throw new ArgumentNullException("No PID was set"); } - string pid = InputPid.Value; + Pid pid = InputPid.Value; SshCommand command = SshResource.SshClient.CreateCommand($"ps -p {pid}"); command.Execute(); diff --git a/OpenTap.Plugins.Ssh/SshKillBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/Background/SshKillBackgroundCommandStep.cs similarity index 92% rename from OpenTap.Plugins.Ssh/SshKillBackgroundCommandStep.cs rename to OpenTap.Plugins.Ssh/Background/SshKillBackgroundCommandStep.cs index 21ddb1c..15289ac 100644 --- a/OpenTap.Plugins.Ssh/SshKillBackgroundCommandStep.cs +++ b/OpenTap.Plugins.Ssh/Background/SshKillBackgroundCommandStep.cs @@ -18,7 +18,7 @@ using System.ComponentModel; using Renci.SshNet; -namespace OpenTap.Plugins.Ssh +namespace OpenTap.Plugins.Ssh.Background { [Display("Kill Background SSH Command", "Kills a command running in the background.", Groups: new[] { "SSH", "Background" })] @@ -27,14 +27,14 @@ public class KillBackgroundSshCommandStep : SshStepBase #region Settings [Display("Process PID", "Select the Background SSH Command to kill")] - public Input InputPid { get; set; } + public Input InputPid { get; set; } #endregion public KillBackgroundSshCommandStep() { Name = "Kill Background SSH Command: PID={Process PID}"; - InputPid = new Input(); + InputPid = new Input(); } public override void Run() @@ -43,7 +43,7 @@ public override void Run() { throw new ArgumentNullException("No PID was set"); } - string pid = InputPid.Value; + Pid pid = InputPid.Value; SshCommand command = SshResource.SshClient.CreateCommand($"kill {pid}"); command.Execute(); From c6eb9e945092cd4b805f0e16e5015f18b94b80dc Mon Sep 17 00:00:00 2001 From: Mattia Lecci Date: Thu, 17 Apr 2025 16:17:17 +0200 Subject: [PATCH 5/7] Centralize bg processes operations and tracking to SshResource --- .../Background/SshBackgroundCommandStep.cs | 9 +- .../SshCheckBackgroundCommandStep.cs | 8 +- .../SshKillBackgroundCommandStep.cs | 17 +-- OpenTap.Plugins.Ssh/SshResource.cs | 119 ++++++++++++++++++ 4 files changed, 124 insertions(+), 29 deletions(-) diff --git a/OpenTap.Plugins.Ssh/Background/SshBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/Background/SshBackgroundCommandStep.cs index 4c4d25c..490987e 100644 --- a/OpenTap.Plugins.Ssh/Background/SshBackgroundCommandStep.cs +++ b/OpenTap.Plugins.Ssh/Background/SshBackgroundCommandStep.cs @@ -40,14 +40,7 @@ public BackgroundSshCommandStep() public override void Run() { - // nohup allows the command to run even when the SSH session ends - // output is suppressed - // the PID of the last background process '$!' is printed to output - SshCommand command = SshResource.SshClient.CreateCommand($"nohup {Command} > /dev/null 2>&1 & echo $!"); - string output = command.Execute(); - pid = new Pid(output); - - Log.Debug("Running full command: " + command.CommandText); + pid = SshResource.StartBackgroundProcess(Command); Log.Info($"Running command `{Command}` in the background"); } } diff --git a/OpenTap.Plugins.Ssh/Background/SshCheckBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/Background/SshCheckBackgroundCommandStep.cs index adde0a3..a276f9d 100644 --- a/OpenTap.Plugins.Ssh/Background/SshCheckBackgroundCommandStep.cs +++ b/OpenTap.Plugins.Ssh/Background/SshCheckBackgroundCommandStep.cs @@ -39,16 +39,14 @@ public CheckBackgroundSshCommandStep() public override void Run() { - if (InputPid == null) + if (InputPid == null || InputPid.Value == null) { throw new ArgumentNullException("No PID was set"); } Pid pid = InputPid.Value; - SshCommand command = SshResource.SshClient.CreateCommand($"ps -p {pid}"); - command.Execute(); - - if (command.ExitStatus == 0) + bool isRunning = SshResource.IsBackgroundProcessRunning(pid); + if (isRunning) { Log.Info($"Process with PID={pid} is alive"); UpgradeVerdict(Verdict.Pass); diff --git a/OpenTap.Plugins.Ssh/Background/SshKillBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/Background/SshKillBackgroundCommandStep.cs index 15289ac..0675230 100644 --- a/OpenTap.Plugins.Ssh/Background/SshKillBackgroundCommandStep.cs +++ b/OpenTap.Plugins.Ssh/Background/SshKillBackgroundCommandStep.cs @@ -45,27 +45,12 @@ public override void Run() } Pid pid = InputPid.Value; - SshCommand command = SshResource.SshClient.CreateCommand($"kill {pid}"); - command.Execute(); - - if (command.ExitStatus == 0) - { - Log.Debug($"Gracefully killed PID={pid}"); - UpgradeVerdict(Verdict.Pass); - return; - } - - command = SshResource.SshClient.CreateCommand($"kill -9 {pid}"); - command.Execute(); - - if (command.ExitStatus == 0) + if (SshResource.KillBackgroundProcess(pid)) { - Log.Debug($"SIGKILLed PID={pid}"); UpgradeVerdict(Verdict.Pass); return; } - Log.Error($"Failed killing PID={pid}"); UpgradeVerdict(Verdict.Fail); } } diff --git a/OpenTap.Plugins.Ssh/SshResource.cs b/OpenTap.Plugins.Ssh/SshResource.cs index 3ebaa19..4d13012 100644 --- a/OpenTap.Plugins.Ssh/SshResource.cs +++ b/OpenTap.Plugins.Ssh/SshResource.cs @@ -13,7 +13,10 @@ //limitations under the License. using Renci.SshNet; +using System; +using System.Collections.Generic; using System.ComponentModel; +using System.Security.Cryptography; namespace OpenTap.Plugins.Ssh { @@ -32,12 +35,15 @@ public abstract class SshResource : Resource public bool LazyConnectSsh { get; set; } = false; [Display("Lazy SCP connection", "Connect SCP client lazily (when it is needed by a Test Step) instead of at the beginning of the Test Plan run.", "Advanced", Order: 7)] public bool LazyConnectScp { get; set; } = true; + + public List BackgroundProcesses { get; set; } #endregion public SshResource() { Name = "Ssh"; Connection = new SshConnectionInfo() { Owner = this }; + BackgroundProcesses = new List(); } protected SshResource(bool session, ITestStep step) { @@ -45,6 +51,7 @@ protected SshResource(bool session, ITestStep step) Connection = new SshConnectionInfo() { Owner = this }; _step = step; IsSession = session; + BackgroundProcesses = new List(); } /// @@ -106,6 +113,13 @@ public override void Open() /// public override void Close() { + // Close all bakground processes before disconnecting ssh client + if (_KillAllBackgroundProcesses()) + if (!_KillAllBackgroundProcesses()) + { + Log.Warning("Some background processes could not be killed correctly"); + } + IsOpened = false; if (sshClient != null) sshClient.Disconnect(); @@ -129,5 +143,110 @@ public override string ToString() if (IsSession) return _step.GetFormattedName(); return base.ToString() + $"({Connection.Username}@{Connection.Host}:{Connection.Port})"; } + + // + // Starts a process with the given command in the background + // The process PID is stored in BackgroundProcesses to keep track of all processes started by this SshResource + // + public Pid StartBackgroundProcess(string command) + { + // nohup allows the command to run even when the SSH session ends + // output is suppressed + // the PID of the last background process '$!' is printed to output + SshCommand sshCmd = SshClient.CreateCommand($"nohup {command} > /dev/null 2>&1 & echo $!"); + string cmdOut = sshCmd.Execute(); + + Log.Debug("Running command: " + sshCmd.CommandText); + + Pid pid = new Pid(cmdOut); + BackgroundProcesses.Add(pid); + return pid; + } + + // + // Checks if background process with the given pid is running + // This only works if the process was started within the same session of this SshResource + // + public bool IsBackgroundProcessRunning(Pid pid) + { + if (!BackgroundProcesses.Contains(pid)) + { + Log.Debug($"PID={pid} was not started in this session or it is not alive anymore"); + return false; + } + + SshCommand command = SshClient.CreateCommand($"ps -p {pid}"); + command.Execute(); + + if (command.ExitStatus == 0) + { + Log.Debug($"Process with PID={pid} is alive"); + return true; + } + + Log.Debug($"Process with PID={pid} is not alive. Removing it from the list of background processes"); + BackgroundProcesses.Remove(pid); + return false; + } + + // + // Kills a background process + // This only works if the process was started within the same session of this SshResource + // + public bool KillBackgroundProcess(Pid pid) + { + if (!IsBackgroundProcessRunning(pid)) + { + Log.Debug($"No process with PID={pid} to be killed"); + return false; + } + + SshCommand command = SshClient.CreateCommand($"kill {pid}"); + command.Execute(); + + if (command.ExitStatus == 0) + { + Log.Debug($"Gracefully killed PID={pid}"); + BackgroundProcesses.Remove(pid); + return true; + } + + command = SshClient.CreateCommand($"kill -9 {pid}"); + command.Execute(); + + if (command.ExitStatus == 0) + { + Log.Debug($"SIGKILLed PID={pid}"); + BackgroundProcesses.Remove(pid); + return true; + } + + Log.Error($"Failed killing PID={pid}"); + return false; + } + + // + // Iterates over all background processes, killing them if they are still running + // If all processes were killed correctly, it returns true, otherwise it returns false + // + private bool _KillAllBackgroundProcesses() + { + Log.Debug("Killing all background processes"); + + bool killedAll = true; + while (BackgroundProcesses.Count > 0) + { + Pid pid = BackgroundProcesses[0]; + bool killed = KillBackgroundProcess(pid); + + if (!killed) + { + killedAll = false; + Log.Debug($"Process with PID={pid} could not be killed correctly"); + } + } + + return killedAll; + } } } From 5ed4721c643b437525e0915a7019e44b4aa74e81 Mon Sep 17 00:00:00 2001 From: Mattia Lecci Date: Thu, 17 Apr 2025 16:24:09 +0200 Subject: [PATCH 6/7] fix commit issue --- OpenTap.Plugins.Ssh/SshResource.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenTap.Plugins.Ssh/SshResource.cs b/OpenTap.Plugins.Ssh/SshResource.cs index 4d13012..9639d47 100644 --- a/OpenTap.Plugins.Ssh/SshResource.cs +++ b/OpenTap.Plugins.Ssh/SshResource.cs @@ -114,7 +114,6 @@ public override void Open() public override void Close() { // Close all bakground processes before disconnecting ssh client - if (_KillAllBackgroundProcesses()) if (!_KillAllBackgroundProcesses()) { Log.Warning("Some background processes could not be killed correctly"); From 9a9f3e0aaca5ab4e048f1f593f3a686d2fe7b6d4 Mon Sep 17 00:00:00 2001 From: Mattia Lecci Date: Thu, 17 Apr 2025 16:30:52 +0200 Subject: [PATCH 7/7] Add "linux only" information --- OpenTap.Plugins.Ssh/Background/SshBackgroundCommandStep.cs | 2 +- .../Background/SshCheckBackgroundCommandStep.cs | 2 +- OpenTap.Plugins.Ssh/Background/SshKillBackgroundCommandStep.cs | 2 +- OpenTap.Plugins.Ssh/SshResource.cs | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/OpenTap.Plugins.Ssh/Background/SshBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/Background/SshBackgroundCommandStep.cs index 490987e..265cbe7 100644 --- a/OpenTap.Plugins.Ssh/Background/SshBackgroundCommandStep.cs +++ b/OpenTap.Plugins.Ssh/Background/SshBackgroundCommandStep.cs @@ -21,7 +21,7 @@ namespace OpenTap.Plugins.Ssh.Background { - [Display("Background SSH Command", "Run a command in the background using a session setup by an SSH Session step, SSH Instrument or SSH Dut.", Groups: new[] { "SSH", "Background" })] + [Display("Background SSH Command", "Run a command in the background using a session setup by an SSH Session step, SSH Instrument or SSH Dut.", Groups: new[] { "SSH", "Background (Linux only)" })] public class BackgroundSshCommandStep : SshStepBase { #region Settings diff --git a/OpenTap.Plugins.Ssh/Background/SshCheckBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/Background/SshCheckBackgroundCommandStep.cs index a276f9d..26fb7a9 100644 --- a/OpenTap.Plugins.Ssh/Background/SshCheckBackgroundCommandStep.cs +++ b/OpenTap.Plugins.Ssh/Background/SshCheckBackgroundCommandStep.cs @@ -21,7 +21,7 @@ namespace OpenTap.Plugins.Ssh.Background { - [Display("Check Background SSH Command", "Checks if a background command is still running.", Groups: new[] { "SSH", "Background" })] + [Display("Check Background SSH Command", "Checks if a background command is still running.", Groups: new[] { "SSH", "Background (Linux only)" })] public class CheckBackgroundSshCommandStep : SshStepBase { #region Settings diff --git a/OpenTap.Plugins.Ssh/Background/SshKillBackgroundCommandStep.cs b/OpenTap.Plugins.Ssh/Background/SshKillBackgroundCommandStep.cs index 0675230..6106e01 100644 --- a/OpenTap.Plugins.Ssh/Background/SshKillBackgroundCommandStep.cs +++ b/OpenTap.Plugins.Ssh/Background/SshKillBackgroundCommandStep.cs @@ -21,7 +21,7 @@ namespace OpenTap.Plugins.Ssh.Background { - [Display("Kill Background SSH Command", "Kills a command running in the background.", Groups: new[] { "SSH", "Background" })] + [Display("Kill Background SSH Command", "Kills a command running in the background.", Groups: new[] { "SSH", "Background (Linux only)" })] public class KillBackgroundSshCommandStep : SshStepBase { #region Settings diff --git a/OpenTap.Plugins.Ssh/SshResource.cs b/OpenTap.Plugins.Ssh/SshResource.cs index 9639d47..c8ff8de 100644 --- a/OpenTap.Plugins.Ssh/SshResource.cs +++ b/OpenTap.Plugins.Ssh/SshResource.cs @@ -146,6 +146,7 @@ public override string ToString() // // Starts a process with the given command in the background // The process PID is stored in BackgroundProcesses to keep track of all processes started by this SshResource + // NOTE: this only works in Linux systems // public Pid StartBackgroundProcess(string command) { @@ -165,6 +166,7 @@ public Pid StartBackgroundProcess(string command) // // Checks if background process with the given pid is running // This only works if the process was started within the same session of this SshResource + // NOTE: this only works in Linux systems // public bool IsBackgroundProcessRunning(Pid pid) { @@ -191,6 +193,7 @@ public bool IsBackgroundProcessRunning(Pid pid) // // Kills a background process // This only works if the process was started within the same session of this SshResource + // NOTE: this only works in Linux systems // public bool KillBackgroundProcess(Pid pid) {