From 8f24c028dd45f551bb7764549512c217e93cbb35 Mon Sep 17 00:00:00 2001 From: Guillaume Bau Date: Tue, 21 Jan 2025 15:25:46 +0100 Subject: [PATCH 1/2] Tezt/Cloud: allows to run command and detach them --- tezt/lib_cloud/agent.ml | 26 ++++++++++++++++++++++++-- tezt/lib_cloud/agent.mli | 2 +- tezt/tests/cloud/basic.ml | 22 +++++++++++++++++++++- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/tezt/lib_cloud/agent.ml b/tezt/lib_cloud/agent.ml index 83af4122bf62..2a37d5874266 100644 --- a/tezt/lib_cloud/agent.ml +++ b/tezt/lib_cloud/agent.ml @@ -134,10 +134,32 @@ let host_run_command agent cmd args = | Some cmd_wrapper -> Process.spawn cmd_wrapper.Gcloud.cmd (cmd_wrapper.args @ [cmd] @ args) -let docker_run_command agent cmd args = +let docker_run_command agent ?(detach = false) cmd args = + (* This function allows to run a command and detach it from the terminal + session and parent process. This allows to run a command in background + without the session (and processes group) being killed by ssh on + disconnection. It uses the [setsid -f] to detach the session. *) + let run_detached ?runner cmd args = + let whole_cmd = String.concat " " (cmd :: args) in + let cmd = "sh" in + let args = + "-c" + :: [ + "setsid -f " ^ whole_cmd ^ " > " + ^ Temp.file ?runner (cmd ^ ".log") + ^ " 2>&1"; + ] + in + (cmd, args) + in match agent.runner with - | None -> Process.spawn cmd args + | None -> + let cmd, args = if detach then run_detached cmd args else (cmd, args) in + Process.spawn cmd args | Some runner -> + let cmd, args = + if detach then run_detached ~runner cmd args else (cmd, args) + in let cmd, args = Runner.wrap_with_ssh runner (Runner.Shell.cmd [] cmd args) in diff --git a/tezt/lib_cloud/agent.mli b/tezt/lib_cloud/agent.mli index 48a917c3d419..01619aa6cc45 100644 --- a/tezt/lib_cloud/agent.mli +++ b/tezt/lib_cloud/agent.mli @@ -61,7 +61,7 @@ val host_run_command : t -> string -> string list -> Process.t The library uses it to ensure there won't be any check of the host when issuing for the first time an ssh connection. *) -val docker_run_command : t -> string -> string list -> Process.t +val docker_run_command : t -> ?detach:bool -> string -> string list -> Process.t (** [copy ?refresh ?is_directory ?destination agent ~source] copies the file into the [agent] directory and returns the directory where the file diff --git a/tezt/tests/cloud/basic.ml b/tezt/tests/cloud/basic.ml index 9b8325df3eb4..e9ef1d7c96f0 100644 --- a/tezt/tests/cloud/basic.ml +++ b/tezt/tests/cloud/basic.ml @@ -59,6 +59,26 @@ let run_vm () = (String.concat " " cmd) ; unit +let run_detached () = + Cloud.register + ~vms:[Configuration.make ()] + ~__FILE__ + ~tags:["run"; "detach"; Tag.cloud] + ~title:"Run a command and detach in a vm" + @@ fun t -> + let agents = Cloud.agents t in + let agent = List.nth agents 0 in + Log.info "Run a command and detach. You should not wait" ; + let* _ = + Agent.docker_run_command ~detach:true agent "sleep" ["10"] |> Process.wait + in + Log.info "OK" ; + Log.info "Run a command without detaching. You should wait 10sec" ; + let* _ = Agent.docker_run_command agent "sleep" ["10"] |> Process.wait in + Log.info "OK" ; + unit + let register () = simple () ; - run_vm () + run_vm () ; + run_detached () -- GitLab From 7f96c4522e5e94c43b71f7ce36fa88f988e34e9a Mon Sep 17 00:00:00 2001 From: Guillaume Bau Date: Tue, 21 Jan 2025 17:20:43 +0100 Subject: [PATCH 2/2] Tezt/Cloud: add some comments --- tezt/lib_cloud/agent.ml | 7 ++++--- tezt/lib_cloud/agent.mli | 9 +++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tezt/lib_cloud/agent.ml b/tezt/lib_cloud/agent.ml index 2a37d5874266..c0d6c8937814 100644 --- a/tezt/lib_cloud/agent.ml +++ b/tezt/lib_cloud/agent.ml @@ -136,9 +136,10 @@ let host_run_command agent cmd args = let docker_run_command agent ?(detach = false) cmd args = (* This function allows to run a command and detach it from the terminal - session and parent process. This allows to run a command in background - without the session (and processes group) being killed by ssh on - disconnection. It uses the [setsid -f] to detach the session. *) + session and parent process. This allows to run a command in background + without the session (and processes group) being killed by ssh on + disconnection. It uses the [setsid -f] to detach the session. + Automatically log stdout and stderr of the command in tezt temporary dir *) let run_detached ?runner cmd args = let whole_cmd = String.concat " " (cmd :: args) in let cmd = "sh" in diff --git a/tezt/lib_cloud/agent.mli b/tezt/lib_cloud/agent.mli index 01619aa6cc45..e4ab61ddd335 100644 --- a/tezt/lib_cloud/agent.mli +++ b/tezt/lib_cloud/agent.mli @@ -12,7 +12,7 @@ type t (** [make ?zone ?ssh_id ?point ~configuration ~next_available_port ~name ()] creates an [agent] from the given parameters. [~next_available_port] should - always provide an available port or raise [Not_found] otherwise. + always provide an available port or raise [Not_found] otherwise. [~name] is the name of the agent. [?ssh_id] and [?point] are used to potentially create a [runner] for the [agent]. *) val make : @@ -60,10 +60,15 @@ val host_run_command : t -> string -> string list -> Process.t The library uses it to ensure there won't be any check of the host when issuing for the first time an ssh connection. + + [detach] Allows the command to be run in background and detaching from the + owning terminal and parent process. In this case, a temporary file is + automatically created in /tmp/tezt-$n with the name of the command as + prefix (warning: it can causes duplicates). *) val docker_run_command : t -> ?detach:bool -> string -> string list -> Process.t -(** [copy ?refresh ?is_directory ?destination agent ~source] copies the file +(** [copy ?refresh ?is_directory ?destination agent ~source] copies the file into the [agent] directory and returns the directory where the file can be found if [?refresh] is set to [true]. It is assumed the [~source] file does not exist on the agent machine. If the parent directory does -- GitLab