【问题标题】:How to trick shebang to allow multiple parameters?如何欺骗shebang以允许多个参数?
【发布时间】:2017-12-27 11:44:57
【问题描述】:

是否知道大多数 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 行而无效,因此唯一可接受的解决方法是同时也是注释,也以“#”开头。

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

【问题讨论】:

  • 要启动的可执行文件是 python 吗?因为还有这个相关的问题:stackoverflow.com/questions/17458528/…
  • 您引用的解决方法是针对 awk,而不是针对 python。
  • 您对 YAML 的解决方法或通用解决方案感兴趣吗?在前一种情况下,请告诉我们最终应该使用哪个可执行文件来使用文件的内容?
  • YAML 的解决方法,我已经有 3 个使用 YAML 的工具。

标签: bash shell shebang


【解决方案1】:

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

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

【讨论】:

  • 谢谢,但如果可能的话,我仍在寻找一个独立的解决方案。
【解决方案2】:

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

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

我们使用 shell 的 HERE-doc 功能和 YAML 文档结束标记 ... 来表示 shell 输入的结束位置。请注意,这仅适用于可以接受来自 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 文件描述符跳过该文件的前3 行,ansible-playbook 将其视为普通可读文件。

【讨论】:

    猜你喜欢
    • 2013-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-07
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    相关资源
    最近更新 更多