如何解决在bash脚本中执行`sh -c`
我有一个"application/json"
文件,该文件将bash命令作为参数,它执行一些逻辑,即设置和检查一些env var,然后执行该输入命令。
resp,err := http.Post(target,"application/json",bytes.NewBuffer([]byte("{\"email\":\"testtestetetsees@mail.ru\",\"deviceId\":\"ftefst891\",\"password\":\"qwertyQwerty132\"}")))
当我运行它时,这是输出
test.sh
但是问题是,当我传递类似#!/bin/bash
#Some other logic here
echo "Run command: $@"
eval "$@"
之类的内容时,我没有得到输出。
% ./test.sh echo "ok"
Run command: echo ok
ok
因此,我尝试将sh -c 'echo "ok"'
更改为% ./test.sh sh -c 'echo "ok"'
Run command: sh -c echo "ok"
%
,尝试直接执行eval
(没有exec
或$@
),甚至尝试执行并保存输出到变量,仍然没有用。
有什么方法可以以这种格式运行传递的命令并获取输出?
用例: 该脚本用作Docker容器的入口点,它从docker CMD接收参数并执行那些参数以运行容器。
作为一个快速修复程序,我可以删除eval
并在不带命令的情况下传递命令,但是我想使脚本可重用,而不希望更改命令。
解决方法
TL; DR:
这是一个典型的用例(在运行复合命令之前,先在Docker入口点脚本中执行一些业务逻辑,如命令行所示),脚本的建议最后一行是:
exec "$@"
详细信息
为进一步解释这一行,请提供一些说明和超链接:
-
根据Bash user manual,
exec
是内置的POSIX Shell,可以替换外壳(使用提供的命令)不创建新进程 。 -
因此,在Docker入口点上下文中像这样使用
exec
很重要,因为它可以确保执行的CMD
程序仍然具有PID 1并可以直接处理信号,包括docker stop
的信号(另请参见其他SO答案:Speed up docker-compose shutdown)。 -
双引号(
"$@"
)对于避免单词拆分也很重要(即,确保每个位置参数按原样传递,即使它包含空格也是如此)。参见例如:#!/usr/bin/env bash printargs () { for arg; do echo "$arg"; done; } test0 () { echo "test0:" printargs $@ } test1 () { echo "test1:" printargs "$@" } test0 /bin/sh -c 'echo "ok"' echo test1 /bin/sh -c 'echo "ok"'
test0: /bin/sh -c echo "ok" test1: /bin/sh -c echo "ok"
-
最后
eval
是一个强大的bash内置函数,它(1)在您的用例中是不需要的,(2)并且实际上不建议一般使用,尤其出于安全性原因强>。例如,如果eval
的字符串参数依赖于用户提供的某些输入…有关此问题的详细信息,请参见例如https://mywiki.wooledge.org/BashFAQ/048(概括了一些人希望使用此内置函数的情况,通常是命令eval "$(ssh-agent -s)"
。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。