John Gordon
John Gordon

Reputation: 33343

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?

Upvotes: 1

Views: 6188

Answers (3)

sbkm
sbkm

Reputation: 142

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

Upvotes: 1

JM0
JM0

Reputation: 447

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)

Upvotes: 3

omajid
omajid

Reputation: 15223

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.

Upvotes: 1

Related Questions