在 Ubuntu 中,是否有一种惯用的方法可以在机器第一次启动时运行脚本?(EC2)。
答案1
不可以。但您可能希望将脚本放入/etc/init.d/script
,然后自行删除它:
#!/bin/bash
echo "Bump! I'm your first-boot script."
# Delete self
rm "${0}"
答案2
结合前两个答案假设你命名你的脚本/usr/local/bin/firstboot.sh
放在末尾/etc/rc.local
(这个脚本在每次启动时运行)脚本如下
更新 2022:将脚本放入 crontab 中,如下所示
@reboot /usr/local/bin/firstboot.sh
#!/bin/bash
FLAG="/var/log/firstboot.log"
if [[ ! -f $FLAG ]]; then
#Put here your initialization sentences
echo "This is the first boot"
#the next line creates an empty file so it won't run the next boot
touch "$FLAG"
else
echo "Do nothing"
fi
答案3
脚本运行时创建跟踪文件。如果文件已存在,则退出脚本。
答案4
我对搜索定义明确且受支持的 Ubuntu“首次启动”钩子的结果感到惊讶。似乎 Red Hat / Fedora / CentOS 群体已经掌握了这一点十多年。最接近的 Ubuntu 等效产品似乎是oem-配置-首次启动。
简单执行的想法是rm $0
可行的。但是,从技术上讲,这涉及到一些有趣的语义。与 Unix 下的大多数其他脚本解释器不同,shell 脚本一次读取和处理一行/语句。如果您从其rm
下方取消链接 () 文件,则处理该脚本的 shell 实例现在正在处理匿名文件(任何打开但未链接的文件)。
考虑这样的文件:
#!/bin/bash
rm $0
echo "I've removed myself: $0"
ls -l $0
cat <<COMMENTARY
This is a test.
I'm still here, because the "here" doc is being fed to 'cat'
via the anonymous file through the open file descriptor.
But I cannot be re-exec'd
COMMENTARY
exec $0
如果你将其保存为类似的内容rmself.sh
并将其(硬)链接到类似的内容tst
,则运行./tst
应该会显示类似这样的输出:
$ ./tst
I've removed myself: ./tst
ls: ./tst: No such file or directory
This is a test.
I'm still here, because the "here" doc is being fed to 'cat'
via the anonymous file through the open file descriptor.
But I cannot be re-exec'd
./tst: line 11: /home/jimd/bin/tst: No such file or directory
./tst: line 11: exec: /home/jimd/bin/tst: cannot execute: No such file or directory
现在,对于符号链接以及脚本作为裸名称调用的情况(强制 shell 搜索脚本),可能存在一些奇怪的极端情况$PATH
。
但似乎bash
(至少在 3.2 版中)$0
如果搜索了路径,则在路径前面添加路径,否则将 $0 设置为用于调用脚本的相对或绝对路径。它似乎没有对相对路径或符号链接进行任何规范化或解析。
对于 Ubuntu 来说,最干净的“首次启动”可能是创建一个小包(.deb),其中包含要放置的脚本和用于将其链接到运行级别 1( )/etc/init.d/firstboot
的安装后脚本(使用类似命令:)...然后让最后一行执行停用或删除,例如:update-rc.d
/etc/rc1.d
update-rc.d firstboot defaults
update-rc.d firstboot disable