仅在首次启动时运行脚本

仅在首次启动时运行脚本

在 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.dupdate-rc.d firstboot defaultsupdate-rc.d firstboot disable

以下是Debian update-rc.d 操作指南

相关内容