Skip to content

Doc Update: Compatible shells for SSHManager#41285

Closed
SamuraiAku wants to merge 1 commit intoJuliaLang:masterfrom
SamuraiAku:SSHManager_shell_cmds
Closed

Doc Update: Compatible shells for SSHManager#41285
SamuraiAku wants to merge 1 commit intoJuliaLang:masterfrom
SamuraiAku:SSHManager_shell_cmds

Conversation

@SamuraiAku
Copy link
Copy Markdown
Contributor

@SamuraiAku SamuraiAku commented Jun 20, 2021

Original Post below. Kept to provide context to the final resolution.


This PR resolves an issue that I had using SSHManager (v1.6.1) under the tcsh shell in Linux. The problem was that the shell command that spawns the worker on the remote machine wasn’t working.

I determined that the problem was that the ssh shell command included two commands to be executed on the remote machine

  1. Launch a shell
  2. Launch Julia

These two commands are currently delimited by a “\n” which works for many shells, but not for tcsh for some reason. As a result, the worker never launches and addproc() fails.

I fixed this by replacing the “\n” with a “; ”. This allowed the worker process to spawn. I also tested it with zsh on an M1 MacBook and that worked as well.

To the best of my knowledge about shell commands, I don’t think that this change would break any other shells. But feedback from others more knowledgeable than myself is appreciated.

@DilumAluthge DilumAluthge requested a review from mgkuhn June 20, 2021 01:23
@mgkuhn mgkuhn self-assigned this Jun 20, 2021
@mgkuhn
Copy link
Copy Markdown
Contributor

mgkuhn commented Jun 20, 2021

SSHManager currently only supports two types of shell: shell=:posix and shell=:wincmd.

The POSIX shell evolved out of the Korn shell (ksh) and both Bash and Zsh are widely used POSIX-compatible shells. In contrast, csh and tcsh are not POSIX shells. They have a quite different syntax, for example when it comes to the details of escaping meta-characters in strings. Unescaped newline characters not being allowed in quoted strings is not the only difference between a POSIX shell and (t)csh.

I wouldn't try to make shell=:posix tcsh compatible unless we can do that easily in a way that is fully transparent for all meta characters passed on as parameters here (working directory, julia executable path, environment variables, command-line arguments).

We can add proper SSHManager support for shell=:csh, which I suspect will require at least replacing the outermost call to string_escape_posixly with a new string_escape_csh function.

I'd be happy to prepare a properly tested (t)csh-support PR if there really is a user requirement for that. Frankly, I hadn't realized that tcsh is still being used today. I had thought csh-derivates had widely fallen out of favour following Tom Christiansen's Csh Programming Considered Harmful postings in the mid 1990s; I hadn't used it myself for the past quarter century (until starting to test SSHManager with it this morning). (I suspect it may still be the default setting on older OSX accounts.)

Having said all that: I'm not sure why the current shell=:posix code uses newlines (I merely preserved them when I rewrote that code). These newlines can be replaced, but if we do that, I would go for using the compacter single-line POSIX-shell syntax

cd DIR && VAR1=VALUE1 VAR2=VALUE2 ... julia ARG1 ARG2 ...

which doesn't use any ;. The problem with the semicolon is that it suppresses the error return value in case the preceding command (here: cd) fails. There is also no point in using the export command if there is only a single command (i.e., julia) to follow that needs to see these.

@SamuraiAku
Copy link
Copy Markdown
Contributor Author

That was an interesting history lesson in shells.

As for why I'm using tcsh, it's because that was the default on the system I'm using. I don't like shell scripting at all and so the distinctions between bash and tcsh don't mean a whole lot to me. Why is the default tcsh? I'm not certain but this quora answer sounds about right.
Shell Scripting: Why do so many people still use tcsh when bash is available?

I'm thinking that this PR should turn into a documentation update. Add a note to the kwargs documentation saying that csh style shells are not supported. For less sophisticated users (like myself), POSIX compliant is really a synonym for "not Windows". Unless mgkhun is willing to go to the effort of adding csh support.

@SamuraiAku SamuraiAku force-pushed the SSHManager_shell_cmds branch from b1c2309 to 01d9e76 Compare June 24, 2021 01:52
@SamuraiAku SamuraiAku changed the title In SSHManager, change the shell command delimiter from \n to ; Doc Update: Compatible shells for SSHManager Jun 24, 2021
@SamuraiAku
Copy link
Copy Markdown
Contributor Author

@mgkuhn I've backed out the changes to the shell commands and added a note to the documentation. What do you think?

@grandemundo82
Copy link
Copy Markdown

I fixed this by replacing the “\n” with a “; ”. This allowed the worker process to spawn. I also tested it with zsh on an M1 MacBook and that worked as well.

I have the same problem. Could you please clarify how you fixed this please? Thanks

@SamuraiAku
Copy link
Copy Markdown
Contributor Author

I fixed this by replacing the “\n” with a “; ”. This allowed the worker process to spawn. I also tested it with zsh on an M1 MacBook and that worked as well.

I have the same problem. Could you please clarify how you fixed this please? Thanks

@grandemundo82 the answer is to change your default shell. You must be using csh or tcsh like I was. Change your default shell to bash and it should work.

@mgkuhn
Copy link
Copy Markdown
Contributor

mgkuhn commented Jul 1, 2021

I hope to have an alternative PR with proper shell = :csh support ready in a week or two.

Here is a first draft of the csh escaping function that this implementation will require

"""
    shell_escape_csh(s::AbstractString)
    shell_escape_csh(io, s::AbstractString)

This function escapes the meta characters in a string such that the
string returned can be inserted as a single word into a command-line
for interpretation by the Unix C shell (csh, tcsh).

In contrast to the POSIX shell, csh does not support the use of the
backslash character in double-quoted strings. Therefore, this function
wraps strings that might contain metacharacters in single quotes,
except for parts that contain single quotes, which are wrapped in
double quotes instead. Linefeed characters are escaped with a
backslash.

This function should also work for POSIX shells, except if the input
string contains a linefeed (`"\n"`) character.

Note that csh cannot handle the NUL character (`"\0"`).

See also: [`shell_escape_posixly`](@ref)
"""
function shell_escape_csh(io, s::AbstractString)
    i = 1
    while true
        for (r,e) = (r"^[A-Za-z0-9/\._-]+$" => "",
                     r"^[^']*$" => "'", r"^[^\$\`\"]*$" => "\"",
                     r"^[^']+"  => "'", r"^[^\$\`\"]+"  => "\"")
            if ((m = match(r, SubString(s, i))) !== nothing)
                write(io, e)
                write(io, replace(m.match, '\n' => "\\\n"))
                write(io, e)
                i += lastindex(m.match)
                break
            end
        end
        i <= lastindex(s) || break
    end
end
shell_escape_csh(s::AbstractString) = sprint(shell_escape_csh, s;
                                             sizehint = sizeof(s)+2)

using Test
csh(s) = chop(read(Cmd(["csh", "-c", "echo " * shell_escape_csh(s)]), String))
csh_test(s) = csh(s) == s
@testset "shell_escape_csh" begin
    @test csh_test("")
    @test csh_test("a")
    @test csh_test(" ")
    @test csh_test("'")
    @test csh_test("\$")
    @test csh_test("\\")
    @test csh_test("\`")
    @test csh_test("\"")
    @test csh_test("'\"'\"")
    @test csh_test("-a/b")
    @test csh_test("abc'd'\"e")
    @test csh_test(join(' ':'~'))
    @test csh_test(join(' ':'~')*join(' ':'~'))
    @test csh_test("\t")
    @test csh_test("\n")
    @test csh_test("\n\n")
    @test csh_test("'\n\n\"")
end

@mgkuhn
Copy link
Copy Markdown
Contributor

mgkuhn commented Jul 6, 2021

A PR for proper C shell support is now ready at #41485.

@SamuraiAku
Copy link
Copy Markdown
Contributor Author

Thanks for adding this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants