summaryrefslogtreecommitdiff
path: root/bin/sbang
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2016-03-05 04:18:48 -0800
committerTodd Gamblin <tgamblin@llnl.gov>2016-03-05 04:18:48 -0800
commitfc6aa7374a243928af38fd1e583c6c67146951cd (patch)
tree22bb8eba191bd22d62a59cf4960def42ffe545bf /bin/sbang
parent8d2538f205ba9d9d9f0cafd678f500de04a6f144 (diff)
downloadspack-fc6aa7374a243928af38fd1e583c6c67146951cd.tar.gz
spack-fc6aa7374a243928af38fd1e583c6c67146951cd.tar.bz2
spack-fc6aa7374a243928af38fd1e583c6c67146951cd.tar.xz
spack-fc6aa7374a243928af38fd1e583c6c67146951cd.zip
Fix #104, #54: issues with overlong shebang in deep directories.
This does several things: - Add `sbang`: a script to run scripts with long shebang lines. - Documentation for `sbang` is in `bin/sbang`. - Add an `sbang` hook that filters the `bin` directory after install and modifies any scripts wtih shebangs that are too long to use `sbang` instead. - `sbang` is at the top level, so it should be runnable (not much we can do if spack itself is too deep for shebang) - `sbang`, when used as the interpreter, runs the *second* shebang line it finds in a script. - shoud fix issues with too long shebang paths.
Diffstat (limited to 'bin/sbang')
-rwxr-xr-xbin/sbang84
1 files changed, 84 insertions, 0 deletions
diff --git a/bin/sbang b/bin/sbang
new file mode 100755
index 0000000000..ebfbe2e7a1
--- /dev/null
+++ b/bin/sbang
@@ -0,0 +1,84 @@
+#!/bin/bash
+#
+# `sbang`: Run scripts with long shebang lines.
+#
+# Many operating systems limit the length of shebang lines, making it
+# hard to use interpreters that are deep in the directory hierarchy.
+# `sbang` can run such scripts, either as a shebang interpreter, or
+# directly on the command line.
+#
+# Usage
+# -----------------------------
+# Suppose you have a script, long-shebang.sh, like this:
+#
+# 1 #!/very/long/path/to/some/interpreter
+# 2
+# 3 echo "success!"
+#
+# Invoking this script will result in an error on some OS's. On
+# Linux, you get this:
+#
+# $ ./long-shebang.sh
+# -bash: ./long: /very/long/path/to/some/interp: bad interpreter:
+# No such file or directory
+#
+# On Mac OS X, the system simply assumes the interpreter is the shell
+# and tries to run with it, which is likely not what you want.
+#
+#
+# `sbang` on the command line
+# -----------------------------
+# You can use `sbang` in two ways. The first is to use it directly,
+# from the command line, like this:
+#
+# $ sbang ./long-shebang.sh
+# success!
+#
+#
+# `sbang` as the interpreter
+# -----------------------------
+# You can also use `sbang` *as* the interpreter for your script. Put
+# `#!/bin/bash /path/to/sbang` on line 1, and move the original
+# shebang to line 2 of the script:
+#
+# 1 #!/bin/bash /path/to/sbang
+# 2 #!/long/path/to/real/interpreter with arguments
+# 3
+# 4 echo "success!"
+#
+# $ ./long-shebang.sh
+# success!
+#
+# On Linux, you could shorten line 1 to `#!/path/to/sbang`, but other
+# operating systems like Mac OS X require the interpreter to be a
+# binary, so it's best to use `sbang` as a `bash` argument.
+# Obviously, for this to work, `sbang` needs to have a short enough
+# path that *it* will run without hitting OS limits.
+#
+#
+# How it works
+# -----------------------------
+# `sbang` is a very simple bash script. It looks at the first two
+# lines of a script argument and runs the last line starting with
+# `#!`, with the script as an argument. It also forwards arguments.
+#
+
+# First argument is the script we want to actually run.
+script="$1"
+
+# Search the first two lines of script for interpreters.
+lines=0
+while read line && ((lines < 2)) ; do
+ if [[ "$line" = '#!'* ]]; then
+ interpreter="${line#\#!}"
+ fi
+ lines=$((lines+1))
+done < "$script"
+
+# Invoke any interpreter found, or raise an error if none was found.
+if [ -n "$interpreter" ]; then
+ exec $interpreter "$@"
+else
+ echo "error: sbang found no interpreter in $script"
+ exit 1
+fi