Search code examples
python-2.7rhelshebangsoftware-collections

How to use scl command as a script shebang?


If I want to run a specific command (with arguments) under Software Collections, I can use this command:

scl enable python27 "ls /tmp"

However, if I try to make a shell script that has a similar command as its shebang line, I get errors:

$ cat myscript
#!/usr/bin/scl enable python27 "ls /tmp"
echo hello

$ ./myscript
Unable to open /etc/scl/prefixes/"ls!

What am I doing wrong?


Solution

  • The parsing of arguments in the she-bang command is not really defined. From man execve:

    The semantics of the optional-arg argument of an interpreter script vary across implementations. On Linux, the entire string following the interpreter name is passed as a single argument to the interpreter, and this string can include white space. However, behavior differs on some other systems. Some systems use the first white space to terminate optional-arg. On some systems, an interpreter script can have multiple arguments, and white spaces in optional-arg are used to delimit the arguments.

    No matter what, argument splitting based on quote sis not supported. So when you write:

    #!/usr/bin/scl enable python27 "ls /tmp"
    

    It's very possible that what gets invoked is (using bash notation):

    '/usr/bin/scl' 'enable' 'python27' '"ls' '/tmp"'
    

    This is probably why it tries to open the "ls file at /etc/scl/prefixes/"ls

    But it is just as likely that the shebang evaluates to:

    '/usr/bin/scl' 'enable python27 "ls /tmp"'
    

    And that would fail since it wont be able to find a command named enable python27 "ls /tmp" for scl to execute.

    There's a few workarounds you can use.

    You can call your script via scl:

    $ cat myscript
    #!/bin/bash
    echo hello
    
    $ scl enable python27 ./myscript
    hello
    

    You can also use the heredoc notation, but it might lead to subtle issues. I personally avoid this:

    $ cat ./myscript
    #!/bin/bash
    scl enable python27 -- <<EOF
    echo hi
    echo \$X_SCLS
    EOF
    
    $ bash -x myscript 
    + scl enable python27 --
    hi
    python27
    

    You can see one of the gotcha's already: I had to write \$X_SCLS to access the environment variable instead of just $X_SCL.

    Edit: Another option is two have two scripts. One that has the actual code, and the second that simply does scl enable python27 $FIRST_SCRIPT. Then you wont have to remember to enter scl ... manually.