Search code examples
bashnamespaceshashbang

Usage of shebang in file header: is there any option to pass multiple arguments in shebang


I am using a different namespace for my python file execution. using a shebang/hashbang, to execute this script (/bin/bash -c ).

problem faced is shebang only accepts a single argument. even if i pass multiple args its treating it as a single string.

shebang used: #!/sbin/ip netns exec tmp <executable>

Experiment:

  1. single executable using : #!/sbin/ip

    Object " tmp" is unknown, try "ip help".
    
  2. one arg shebang in tmp : #!/sbin/ip netns

    $/bin/bash -c  tmp
    Command "tmp" is unknown, try "ip netns help".
    
  3. with two arg shebang used in tmp: #!/sbin/ip netns exec

    $/bin/bash -c  tmp
    Object "netns exec" is unknown, try "ip help".
    
    • its picking "netns exec" as a single argument
  4. full cmd used

    shebang used in tmp : #!/sbin/ip netns exec global python

    $/bin/bash -c  tmp
    Object "netns exec global python" is unknown, try "ip help".
    

Is there any way to pass multiple argumenets to shebang executable other than chaining files.


Solution

  • Linux (and other OSs I believe) only split the shebang string once, at the first whitespace. So you can only ever pass one argument.

    When you do #!/sbin/ip netns exec tmp <executable>, ip sees one argument string: netns exec tmp <executable> (including spaces).

    But GNU env added the -S option for splitting shebang arguments. It's also available on FreeBSD env. But not busybox env.

    So if you launch your interpreter using env -S:

    #!/usr/bin/env -S command -a -b -c
    

    env will split the three arguments on white space, and pass them to command. env of course is seeing the single argument -S command -a -b -c, but it can parse this.

    I don't know enough about namespaces to know if this is a good idea, but it seemed to work for me:

    $ sudo ip netns add test
    $ sudo ip netns identify
    # (empty)
    
    $ cat /tmp/netns-shebang-test
    #!/usr/bin/env -S ip netns exec test bash
    
    echo "$BASH_VERSION"
    echo "$0"
    ip netns identify
    
    $ sudo /tmp/netns-shebang-test
    5.1.16(1)-release
    /tmp/netns-shebang-test-script
    test
    

    I'm showing bash, but it also worked with a similar python script. I will repeat that I don't know enough about namespaces to know if this is a good approach or not.