如何欺骗shebang允许多个参数?

时间:2017-07-21 12:12:44

标签: bash shell shebang

是否知道大多数shebang实现都支持单个参数,所以如果您有类似

的内容
#!/usr/bin/env some-tool-accepting-yaml param1 param2
... (yaml body)

它现在将按预期工作,因为它将使用" param1 param2"来调用该工具。参数而不是将其分成两个参数。

似乎一个workaround练习是使用类似的东西:

#!/bin/sh
arbitrary_long_name==0 "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"

现在这种方法会因为第二行而使基于YAML的脚本无效,所以唯一可接受的解决方法是也是一个注释,从"#"开始。太

有没有办法绕过这个问题?

2 个答案:

答案 0 :(得分:3)

不使用多语言脚本的一般解决方案

launcher.sh

#!/bin/bash

# first argument to be split
if [[ $- != *f* ]]; then reset=1; fi
set -f
arg=( $1 )
shift
if [[ $reset = 1 ]]; then set +f; fi

# other arguments
arg+=("$@")

# launch command
exec "${arg[@]}"

脚本

#!/path/to/launcher.sh interpreter opts

答案 1 :(得分:0)

没有针对此问题的通用解决方案(除非您使用的是MacOSX,可以在shebang行中传递多个参数),但是对于特定要求的组合,可以使用shell技巧,例如:

#!/bin/sh
exec yamllint -f colored --no-warnings ${1:+-c ${1}} - <<...
---
(YAML document)
...

我们正在使用外壳程序的HERE-doc功能和YAML文档结束标记...来表示外壳程序输入的结束位置。请注意,这仅适用于可以接受来自STDIN的输入的命令。

如果some-tool需要文件名作为输入参数,则可以(ab)使用bash就地文件实现功能,其中命令的输出通过映射的文件描述符传递:

#!/bin/bash
exec ansible-playbook --ask-become-pass ${1:+--extra-vars hostname=${1}} <(tail +3 ${0})
---
- hosts: all
  gather_facts: false
  become: true
  vars_prompt:
    - name: hostname
      prompt: "Hostname"
      private: no

  tasks:
(YAML document)

我们正在传递tail命令的输出,跳过文件的前三行通过/dev/fd/xx文件描述符,ansible-playbook将其视为普通可读文件。 / p>