从 URL 执行 bash 脚本
Posted
技术标签:
【中文标题】从 URL 执行 bash 脚本【英文标题】:Execute bash script from URL 【发布时间】:2011-08-09 18:58:24 【问题描述】:假设我在 URL“http://mywebsite.com/myscript.txt”有一个包含脚本的文件:
#!/bin/bash
echo "Hello, world!"
read -p "What is your name? " name
echo "Hello, $name!"
我想在不先将其保存到文件的情况下运行此脚本。我该怎么做?
现在,我看到了语法:
bash < <(curl -s http://mywebsite.com/myscript.txt)
但这似乎不像我保存到文件然后执行那样工作。例如 readline 不起作用,输出只是:
$ bash < <(curl -s http://mywebsite.com/myscript.txt)
Hello, world!
同样,我试过了:
curl -s http://mywebsite.com/myscript.txt | bash -s --
结果相同。
最初我有一个类似的解决方案:
timestamp=`date +%Y%m%d%H%M%S`
curl -s http://mywebsite.com/myscript.txt -o /tmp/.myscript.$timestamp.tmp
bash /tmp/.myscript.$timestamp.tmp
rm -f /tmp/.myscript.$timestamp.tmp
但这似乎很草率,我想要一个更优雅的解决方案。
我知道有关从 URL 运行 shell 脚本的安全问题,但现在让我们忽略所有这些。
【问题讨论】:
如果您最终创建了一个临时文件,您可能应该使用mktemp
而不是滚动您自己的解决方案
cmd <<foo
是大多数 shell 中的 heredoc 语法,可能不是您想要的。
【参考方案1】:
不直接执行脚本,先下载再执行
SOURCE='https://gist.githubusercontent.com/cci-emciftci/123123/raw/123123/sample.sh'
curl $SOURCE -o ./my_sample.sh
chmod +x my_sample.sh
./my_sample.sh
【讨论】:
【参考方案2】:如果您希望脚本使用当前 shell 运行,无论它是什么,请使用:
$SHELL:-sh -c "$(wget -qO - http://mywebsite.com/myscript.txt)"
如果你有wget
,或者:
$SHELL:-sh -c "$(curl -Ls http://mywebsite.com/myscript.txt)"
如果你有curl
。
如果脚本是交互式的,即它要求用户输入,此命令仍然有效。
注意:默认情况下,OpenWRT 有一个 wget
克隆,但没有 curl
。
【讨论】:
【参考方案3】:对于 bash、Bourne shell 和 fish:
curl -s http://server/path/script.sh | bash -s arg1 arg2
标志“-s”使 shell 从标准输入读取。
【讨论】:
这应该适用于大多数 shell,而接受的答案不适用于 fish,例如。 什么是arg1 arg2
?。我可以打电话给curl -s http://server/path/script.sh | bash -s
吗?
@Nairum 是的,你可以不带arg1和arg2调用,它们是传递给script.sh的参数。如果 script.sh 需要参数才能执行,您可以添加任意数量的参数。有 2 个参数只是一个例子。【参考方案4】:
bash | curl http://your.url.here/script.txt
实际例子:
juan@juan-MS-7808:~$ bash | curl https://raw.githubusercontent.com/JPHACKER2k18/markwe/master/testapp.sh
Oh, wow im alive
juan@juan-MS-7808:~$
【讨论】:
这完全是错误的。在发布之前测试你的脚本,不要伪造输出。【参考方案5】:用途:
curl -s -L URL_TO_SCRIPT_HERE | bash
例如:
curl -s -L http://bitly/10hA8iC | bash
【讨论】:
【参考方案6】:一些无人值守的脚本我使用如下命令:
sh -c "$(curl -fsSL <URL>)"
我建议避免直接从 URL 执行脚本。您应该确保 URL 是安全的并在执行之前检查脚本的内容,您可以在执行之前使用 SHA256 校验和来验证文件。
【讨论】:
【参考方案7】:这种方式既好又传统:
17:04:59@itqx|~
qx>source <(curl -Ls http://192.168.80.154/cent74/just4Test) Lord Jesus Loves YOU
Remote script test...
Param size: 4
---------
17:19:31@node7|/var/www/html/cent74
arch>cat just4Test
echo Remote script test...
echo Param size: $#
【讨论】:
【参考方案8】:最好的方法是
curl http://domain/path/to/script.sh | bash -s arg1 arg2
@user77115 的回答略有变化
【讨论】:
【参考方案9】:我经常用下面的就够了
curl -s http://mywebsite.com/myscript.txt | sh
但是在旧系统(kernel2.4)中,遇到问题,做以下可以解决,我尝试了很多其他的,只有以下工作
curl -s http://mywebsite.com/myscript.txt -o a.sh && sh a.sh && rm -f a.sh
例子
$ curl -s someurl | sh
Starting to insert crontab
sh: _name.sh: command not found
sh: line 208: syntax error near unexpected token `then'
sh: line 208: ` -eq 0 ]]; then'
$
问题可能是网络慢,或者bash版本太旧无法优雅处理网络慢
但是,以下解决了问题
$ curl -s someurl -o a.sh && sh a.sh && rm -f a.sh
Starting to insert crontab
Insert crontab entry is ok.
Insert crontab is done.
okay
$
【讨论】:
【参考方案10】:只需结合 amra 和 user77115 的答案:
wget -qO- https://raw.githubusercontent.com/lingtalfi/TheScientist/master/_bb_autoload/bbstart.sh | bash -s -- -v -v
它执行 bbstart.sh 远程脚本,将 -v -v 选项传递给它。
【讨论】:
【参考方案11】:source <(curl -s http://mywebsite.com/myscript.txt)
应该这样做。或者,不要对您的初始重定向进行重定向,即重定向标准输入; bash
需要一个文件名,无需重定向即可正常执行,<(command)
语法提供了一个路径。
bash <(curl -s http://mywebsite.com/myscript.txt)
看echo <(cat /dev/null)
的输出可能会更清楚
【讨论】:
谢谢,这清楚地说明了发生了什么。只是好奇,使用初始重定向有什么好处?我问是因为对于 RVM 安装,他们使用命令:bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
为什么不只是:bash <(curl -s https://rvm.beginrescueend.com/install/rvm)
小提示:如果 wget 可用但 curl 不可用(例如在现有的 Ubuntu 桌面系统上),您可以将 wget -q http://mywebsite.com/myscript.txt -O -
替换为 curl -s http://mywebsite.com/myscript.txt
。
请注意,您不能将命令行参数传递给脚本。 bash will_not_work foobar <(curl -s http://example.com/myscript.sh)
如果您拥有该脚本,则可以使用环境变量,如下所示:MYFLAG1=will_work bash MYFLAG2=foobar <(curl -s http://example.com/myscript.sh)
它也适用于这样的管道:curl -s http://example.com/myscript.sh | MYFLAG1=will_work MYFLAG2=foobar bash
这当然要求您使用 MYFLAG1 和 MYFLAG2 而不是 $1 和 $2
$ sudo bash xxx) 出错:bash: /dev/fd/63: Bad file descriptor
第一个解决方案(使用源的那个)根本不起作用。第二个有点工作,但有其局限性。它正在子shell 中从URL 执行脚本。我在脚本中定义了一些我想在父级中使用的函数。有没有办法做到这一点?还是我运气不好,唯一的解决方案是将该脚本复制到一个临时文件中,然后获取它?【参考方案12】:
还有:
curl -sL https://.... | sudo bash -
【讨论】:
最后一条是什么意思? 来自 bash 手册页: A -- 表示选项结束并禁用进一步的选项处理。 -- 之后的任何参数都被视为文件名和参数。 - 的参数等价于--。【参考方案13】:这是通过传递一些参数(arg1 arg2)来执行远程脚本的方法:
curl -s http://server/path/script.sh | bash /dev/stdin arg1 arg2
【讨论】:
这会破坏 stty :\ 如果您使用标准输入,请使用bash <(curl ... )
【参考方案14】:
您也可以这样做:
wget -O - https://raw.github.com/luismartingil/commands/master/101_remote2local_wireshark.sh | bash
【讨论】:
【参考方案15】:使用wget
,这通常是默认系统安装的一部分:
bash <(wget -qO- http://mywebsite.com/myscript.txt)
【讨论】:
RTFM:gnu.org/software/wget/manual/wget.html。 ||| -q == --quiet == "关闭 Wget 的输出。" ||| -O- == --output-document=- == 如果使用'-'作为文件,文档将被打印到标准输出。【参考方案16】:试试吧:
bash <(curl -s http://mywebsite.com/myscript.txt)
【讨论】:
以上是关于从 URL 执行 bash 脚本的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Cygwin 在 Jenkins 控制台上显示 bash 脚本执行
从执行 bash 脚本中清除历史记录中的最后一个 bash 命令