【问题标题】:Execute Bash script remotely via cURL通过 cURL 远程执行 Bash 脚本
【发布时间】:2018-09-15 16:59:15
【问题描述】:

我有一个简单的 Bash 脚本,它接受输入并使用该输入打印几行

fortinetTest.sh

read -p "Enter SSC IP: $ip " ip && ip=${ip:-1.1.1.1}
printf "\n"

#check IP validation
if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  echo "SSC IP: $ip"
  printf "\n"
else
  echo "Enter a valid SSC IP address. Ex. 1.1.1.1"
  exit
fi

我尝试将它们上传到我的服务器,然后尝试通过curl 运行它

我不确定为什么我使用 cURL/wget 时输入提示永远不会启动。

我错过了什么吗?

【问题讨论】:

  • 一定要提示吗?似乎 url 参数会更简单。
  • 通过 wget 使用的 curl 不是允许提示/响应的终端仿真器,它是数据的获取器(一种方式)。您需要通过 curl 命令添加 SSC IP 输入(即curl ..sh < 1234 | bash)
  • @PrestonM :我不介意使用您的建议,听起来比我现在尝试做的要好,但我不确定如何调整我的代码以使用从 URL 参数读取.想让我从几行开始?
  • @RandyCasburn,你介意回答吗?你的建议可能适用于我正在尝试做的事情。
  • 我首先不建议直接从curl 运行脚本。良好的安全性要求您首先下载脚本,检查它以确保它是您期望的脚本,然后然后执行它。 curl ... > tmp.sh; <look at it>; bash tmp.sh.

标签: linux bash shell curl


【解决方案1】:

使用curl ... | bash 表单,bash 的标准输入正在读取脚本,因此标准输入不适用于read 命令。

尝试使用Process Substitution 像本地文件一样调用远程脚本:

bash <( curl -s ... )

【讨论】:

  • 非常好!这绝对解决了我提到的问题!
  • 执行过程中如果需要远程资源会怎样?
  • 那么下载脚本显然是错误的解决方案。你会想要ssh -t user@host 'bash script.sh'
  • @glennjackman - 你能举个例子吗?我试过了。似乎不起作用。我不确定我想念什么。
  • “不起作用”是一个无用的问题描述。提供详细信息。
【解决方案2】:

您的问题可以通过运行如下脚本简单地重现

$ cat test.sh | bash
Enter a valid SSC IP address. Ex. 1.1.1.1

这是因为您使用pipe 启动的bash 没有得到TTY,当您执行read -p 时,它是从stdin 读取的,在这种情况下是test.sh 的内容。所以问题不在于卷曲。问题不是从 tty 读取

所以解决方法是确保你从 tty 准备好它

read < /dev/tty -p "Enter SSC IP: $ip " ip && ip=${ip:-1.1.1.1}
printf "\n"

#check IP validation
if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  echo "SSC IP: $ip"
  printf "\n"
else
  echo "Enter a valid SSC IP address. Ex. 1.1.1.1"
  exit
fi

一旦你这样做了,即使curl 也将开始工作

vagrant@vagrant:/var/www/html$ curl -s localhost/test.sh | bash
Enter SSC IP:  2.2.2.2

SSC IP: 2.2.2.2

【讨论】:

    【解决方案3】:

    我个人更喜欢source &lt;(curl -s localhost/test.sh) 选项。虽然它与bash ... 相似,但一个显着的区别是处理流程的方式。

    bash 将导致启动一个新进程,该进程将从脚本中调用命令。
    另一方面,source 将使用当前进程从脚本中调用命令。

    在某些情况下可以起到关键作用。我承认这并不常见。

    为了演示,请执行以下操作:

    ### Open Two Terminals
    # In the first terminal run:
    echo "sleep 5" > ./myTest.sh
    bash ./myTest.sh
    
    # Switch to the second terminal and run:
    ps -efjh
    
    ## Repeat the same with _source_ command
    # In the first terminal run:
    source ./myTest.sh
    
    # Switch to the second terminal and run:
    ps -efjh
    

    结果应如下所示:

    执行前:

    运行bash(主+两个子进程):

    运行source(主+一个子进程):

    更新: bash 和source 使用变量的区别:

    source 命令将使用您当前的环境。这意味着在执行时,脚本所做的所有更改和变量声明都将在您的提示符中可用。

    另一方面,bash 将作为不同的进程运行;因此,当进程退出时,所有变量都将被丢弃。

    我想每个人都会同意每种方法都有优点和缺点。您只需决定哪一个更适合您的用例。

    ## Test for variables declared by the script:
    echo "test_var3='Some Other Value'" > ./myTest3.sh
    bash ./myTest3.sh
    echo $test_var3
    source ./myTest3.sh
    echo $test_var3
    

    ## Test for usability of current environment variables:
    test_var="Some Value" # Setting a variable
    echo "echo $test_var" > myTest2.sh # Creating a test script
    chmod +x ./myTest2.sh # Adding execute permission
    ## Executing:
    . myTest2.sh
    bash ./myTest2.sh
    source ./myTest2.sh
    ./myTest2.sh
    ## All of the above results should print the variable.
    

    我希望这会有所帮助。

    【讨论】:

    • 采购脚本而不是在子进程中运行它们的一个问题是脚本可以改变调用(交互式)shell 的环境。 (例如,弄乱你的PATH、更改提示、设置意外选项、修改 shell 变量、设置信号处理程序等)
    • @GertvandenBerg,您是否遇到过这种情况并且能够重现它?我没有遇到过这样的行为,这就是为什么我不相信它是这种情况。我会用例子更新我的答案。
    • 快速示例是echo PS1=test &gt; test.sh; bash test.sh # no change to prompt in shell that called the script source test.sh # changes the calling shell's prompt。 (source 就是针对这种事情的……)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-21
    • 1970-01-01
    • 2014-08-29
    • 2021-02-17
    • 2011-05-09
    • 1970-01-01
    • 2021-06-15
    相关资源
    最近更新 更多