Skip to content

Commit 6034723

Browse files
committed
addprocs: new keyword arguments env and cmdline_cookie
* generalized mechanics for passing environment variables to workers * `cmdline_cookie` is work around for an ssh problem with Windows workers that run older (pre-ConPTY) Windows or Julia versions
1 parent a0449ae commit 6034723

File tree

3 files changed

+45
-23
lines changed

3 files changed

+45
-23
lines changed

NEWS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ Standard library changes
103103

104104
#### Distributed
105105

106-
* Added keyword argument `shell` to `addprocs`; use `shell=:wincmd` to invoke Windows workers via ssh connections to `cmd.exe`.
106+
* Now supports invoking Windows workers via ssh (via new keyword argument `shell=:wincmd` in `addprocs`) ([#30614])
107107

108-
* Added keyword argument `ssh` to `addprocs` to specify the ssh client path.
108+
* Other new keyword arguments in `addprocs`: `ssh` to specify the ssh client path, `env` to pass environment variables to workers, and `cmdline_cookie` to work around an ssh problem with Windows workers that run older (pre-ConPTY) Windows or Julia versions. ([#30614])
109109

110110
#### Sockets
111111

stdlib/Distributed/src/cluster.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,8 @@ default_addprocs_params() = Dict{Symbol,Any}(
514514
:topology => :all_to_all,
515515
:ssh => "ssh",
516516
:shell => :posix,
517+
:cmdline_cookie => false,
518+
:env => [],
517519
:dir => pwd(),
518520
:exename => joinpath(Sys.BINDIR, julia_exename()),
519521
:exeflags => ``,

stdlib/Distributed/src/managers.jl

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,20 @@ Keyword arguments:
113113
are setup lazily, i.e. they are setup at the first instance of a remote call between
114114
workers. Default is true.
115115
116-
!!! compat "Julia 1.2"
117-
The `ssh` and `shell` keyword arguments were added in Julia 1.2.
116+
* `env`: provide an array of string pairs such as
117+
`env=["JULIA_DEPOT_PATH"=>"/depot"] to request that environment variables
118+
are set on the remote machine. By default only the environment variable
119+
`JULIA_WORKER_TIMEOUT` is passed automatically from the local to the remote
120+
environment.
121+
122+
* `cmdline_cookie`: pass the authentication cookie via the `--worker` commandline
123+
option. The (more secure) default behaviour of passing the cookie via ssh stdio
124+
may hang with Windows workers that use older (pre-ConPTY) Julia or Windows versions,
125+
in which case `cmdline_cookie=true` offers a work-around.
126+
127+
!!! compat "Julia 1.4"
128+
The keyword arguments `ssh`, `shell`, `env` and `cmdline_cookie`
129+
were added in Julia 1.4.
118130
119131
Environment variables:
120132
@@ -161,6 +173,8 @@ function launch_on_machine(manager::SSHManager, machine, cnt, params, launched,
161173
dir = params[:dir]
162174
exename = params[:exename]
163175
exeflags = params[:exeflags]
176+
cmdline_cookie = params[:cmdline_cookie]
177+
env=Dict{String,String}(params[:env]);
164178

165179
# machine could be of the format [user@]host[:port] bind_addr[:bind_port]
166180
# machine format string is split on whitespace
@@ -171,6 +185,11 @@ function launch_on_machine(manager::SSHManager, machine, cnt, params, launched,
171185
if length(machine_bind) > 1
172186
exeflags = `--bind-to $(machine_bind[2]) $exeflags`
173187
end
188+
if cmdline_cookie
189+
exeflags = `$exeflags --worker=$(cluster_cookie())`
190+
else
191+
exeflags = `$exeflags --worker`
192+
end
174193

175194
machine_def = split(machine_bind[1], ':')
176195
# if this machine def has a port number, add the port information to the ssh flags
@@ -191,44 +210,45 @@ function launch_on_machine(manager::SSHManager, machine, cnt, params, launched,
191210

192211
# Build up the ssh command
193212

194-
# the default worker timeout
195-
tval = get(ENV, "JULIA_WORKER_TIMEOUT", "")
213+
# pass on some environment variables by default
214+
for var in ["JULIA_WORKER_TIMEOUT"]
215+
if !haskey(env, var) && haskey(ENV, var)
216+
env[var] = ENV[var]
217+
end
218+
end
219+
for var in keys(ENV)
220+
occursin(r"^[a-zA-Z0-9_]+$", var) || throw(ArgumentError(var))
221+
end
196222

197223
# Julia process with passed in command line flag arguments
198224
if shell == :posix
199225
# ssh connects to a POSIX shell
200226

201-
cmdline_cookie = false
202-
exeflags = `$exeflags --worker`
203-
cmds = """
204-
cd -- $(shell_escape_posixly(dir))
205-
$(isempty(tval) ? "" : "export JULIA_WORKER_TIMEOUT=$(shell_escape_posixly(tval))")
206-
$(shell_escape_posixly(exename)) $(shell_escape_posixly(exeflags))"""
227+
cmds = "$(shell_escape_posixly(exename)) $(shell_escape_posixly(exeflags))"
228+
# set environment variables
229+
for (var, val) in env
230+
cmds = "export $(var)=$(shell_escape_posixly(val))\n$cmds"
231+
end
232+
# change working directory
233+
cmds = "cd -- $(shell_escape_posixly(dir))\n$cmds"
207234

208235
# shell login (-l) with string command (-c) to launch julia process
209236
remotecmd = shell_escape_posixly(`sh -l -c $cmds`)
210237

211238
elseif shell == :wincmd
212239
# ssh connects to Windows cmd.exe
213240

214-
# Passing the cookie via ssh stdin currently hangs with
215-
# Microsoft's Windows port of OpenSSH, so we do it via
216-
# --worker on the command line for now, although that may
217-
# cause the cookie to become visible to other users (e.g.
218-
# using Process Explorer or WMIC).
219-
cmdline_cookie = true
220-
exeflags = `$exeflags --worker=$(cluster_cookie())`
221-
222241
any(c -> c == '"', exename) && throw(ArgumentError("invalid exename"))
223242

224243
remotecmd = shell_escape_wincmd(escape_microsoft_c_args(exename, exeflags...))
244+
# change working directory
225245
if dir !== nothing && dir != ""
226246
any(c -> c == '"', dir) && throw(ArgumentError("invalid dir"))
227247
remotecmd = "pushd \"$(dir)\" && $remotecmd"
228248
end
229-
if tval !== nothing && tval != ""
230-
all(isdigit, tval) || throw(ArgumentError("invalid JULIA_WORKER_TIMEOUT"))
231-
remotecmd = "set JULIA_WORKER_TIMEOUT=$tval && $remotecmd"
249+
# set environment variables
250+
for (var, val) in env
251+
remotecmd = "set $(var)=$(shell_escape_wincmd(val))&& $remotecmd"
232252
end
233253

234254
else

0 commit comments

Comments
 (0)