Background:
A colleague and I are developing a piece of code (called pbsmake) in python that ends up interpreting something that looks like a Makefile. We will use pbsmake to help distribute jobs to a local scheduler (each makefile target gets its own job) but we found that we may want to use the pbsmake interpreter as a shell interpreter itself so we can simply execute certain commands (which are really like makefiles) with a target.
Most of our development has been under GNU/Linux and this works just fine. However, as soon as we do this under OSX Snow Leopard, the top-level makefile starts being executed as if it were a bash script.
How to replicate:
- create a simple interpreter that is a shell script itself:
- /Users/imoverclocked/simple-interp.sh:
- #!/bin/cat
- This is my simple interpreter, it simply spits the file onto STDOUT
- create a script that uses this interpreter:
- /Users/imoverclocked/simple-script.sh:
- #!/Users/imoverclocked/simple/interp.sh
- This is a simple script that is interpreted (really, just spit out by cat)
- try and execute the simple-script.sh
- ./simple-script.sh
- Badly placed ()'s.
- change the interpreter to first invoke /usr/bin/env as a work-around
- /Users/imoverclocked/simple-script.sh:
- #!/usr/bin/env /Users/imoverclocked/simple/interp.sh
- This is a simple script that is interpreted (really, just spit out by cat)
- executing the script now gives the same output as on other unix-like architectures.
- $ ./simple-script.sh#!/bin/catThis is my simple interpreter, it simply spits the file onto STDOUT#!/home/pirl/tims/sh/simple-interp.shThis is a simple script that is interpreted (really, just spit out by cat)
My guess to what is happening is that execv* can't handle the case where a script calls a script to interpret a script. One work-around is to use /usr/bin/env in the "simple-script.sh" header which works since /usr/bin/env is a binary executable which then invokes the script in it's own execvp call.