How to use scl command as a script shebang?

5.6k Views Asked by At

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?

3

There are 3 best solutions below

0
omajid On BEST ANSWER

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.

0
JM0 On

You should try using -- instead of surrounding your command with quotes.

scl enable python27 -- ls /tmp

I was able to make a python script that uses the rh-python35 collection with this shebang:

#!/usr/bin/scl enable rh-python35 -- python

import sys
print(sys.version)
0
sbkm On

The software collections documentation may also be helpful. In particular you can try

cat myscript.sh | scl enable python27 -

As well as permanently enabling a software collection

source scl_source enable python27
./myscript.sh