是否可以编写启动 FreeBSD VM 的脚本,其中 运行 一个程序,并获取结果?
Is it possible to script starting up a FreeBSD VM, running a program in it, and fetching the result?
我有一个库想在 FreeBSD 上测试。我的CI设置没有任何 FreeBSD 系统,添加它们会很困难,但是我可以在里面启动一个 VM我的 CI 脚本。 (事实上,我已经这样做来测试更奇特的 Linux 内核版本。)
对于 Linux,这非常简单:从某个发行版站点获取预构建的机器映像,然后使用 cloud-init 注入第一个 运行 脚本,完成。
是否可以用 FreeBSD 做同样的事情?我正在寻找一种自动化的方法来获取标准的 FreeBSD 机器映像(例如从 https://freebsd.org 下载),启动它,然后将程序注入 运行。棘手的部分是它应该是完全自动化的——我不想每次 FreeBSD 发布新版本时都必须手动点击安装程序。
开箱即用,没有像 cloud-init
这样的选项,但您可以创建自己的图像并在 AWS 中使用 firstboot
for example, this script is used to bootstrap a VM with saltstack:
#!/bin/sh
# KEYWORD: firstboot
# PROVIDE: set_hostname
# REQUIRE: NETWORKING
# BEFORE: login
. /etc/rc.subr
name="set_hostname"
rcvar=set_hostname_enable
start_cmd="set_hostname_run"
stop_cmd=":"
export AWS_ACCESS_KEY_ID=key
export AWS_SECRET_ACCESS_KEY=secret
export AWS_DEFAULT_REGION=region
TAG_NAME="Salt"
INSTANCE_ID=$(/usr/local/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id)
REGION=$(/usr/local/bin/curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed 's/.$//')
TAG_VALUE=$(/usr/local/bin/aws ec2 describe-tags --filters "Name=resource-id,Values=${INSTANCE_ID}" "Name=key,Values=$TAG_NAME" --region ${REGION} --output=text | cut -f5)
set_hostname_run()
{
hostname ${INSTANCE_ID}
sysrc hostname="${INSTANCE_ID}"
sysrc salt_minion_enable="YES"
echo ${INSTANCE_ID} > /usr/local/etc/salt/minion_id
pw usermod root -c "root on ${INSTANCE_ID}"
if [ ! -z "${TAG_VALUE}" ]; then
echo "node_type: ${TAG_VALUE}" > /usr/local/etc/salt/grains
fi
service salt_minion start
}
load_rc_config $name
run_rc_command ""
要创建自己的图像,您可以使用此脚本作为起点:https://github.com/fabrik-red/images/blob/master/fabrik.sh#L124, more info here: https://fabrik.red/post/creating-the-image/
你也可以简单的在Virtualbox中安装FreeBSD,配置与firstboot
相关的脚本,测试,当你对结果满意时,导出它,导出前注意/firstboot
存在(touch /firstboot
) 因为在第一次启动后它将被删除,并且在导出后如果不存在它可能不会调用脚本。
创建映像后,您可以多次使用它,无需每次都创建一个新的 "custom" VM,这完全取决于您用于 bootstrap 和加载的脚本"firstboot".
上的脚本
要 "inject" 您的软件通常需要能够写入文件系统,而最可靠的方法是 运行 系统本身。换句话说,有一个 FreeBSD VM 来创建 FreeBSD VM - 你可以在本地构建它们(man 7 版本),或者从 http://download.FreeBSD.org 获取 VM 映像,将它们的 rootfs 安装在某个地方,将你的软件放在你需要的任何地方,并且让它从挂载文件系统的 /etc/rc.local.
执行
我仔细研究了一下,结果证明这是可能的,虽然很尴尬。
FreeBSD 官方版本分为三种:预装 VM、ISO 安装程序和 U 盘安装程序。
默认情况下,官方预装的 VM 映像不提供任何从外部编写脚本的方式。他们使用 FreeBSD UFS 文件系统,该文件系统无法从任何通用 OS 进行修改。 (Linux 可以以只读方式挂载 UFS,并且有一些用于读写支持的代码,但默认情况下读写支持是禁用的,需要自定义内核。)所以没有简单的方法以编程方式修改它们,除非您已经安装了 FreeBSD。
USB 记忆棒安装程序也使用 UFS 文件系统,所以已经过时了。我发现的预构建 live CD 也是如此,比如 mfsBSD(CD 本身是 iso9660,但它只是一个解压到内存中的大 UFS blob 的容器)。
这样就剩下 CD 安装程序了。事实证明,这些实际上使用 iso9660 作为其实际文件布局。而且我们不需要 FreeBSD 来使用 iso9660!
所以你要做的是:
- 下载 CD 安装程序
- 修改其上的文件以在无需用户交互的情况下进行安装,将一些自定义配置应用于新系统,然后关闭
- 使用您最喜欢的 VM 运行器启动带有空白硬盘驱动器映像的 CD,然后让它 运行 在该硬盘驱动器上安装 FreeBSD
- 启动硬盘,随心所欲。
我忽略了大量繁琐的细节,但这是基本的想法。这里还有一个完整的示例:https://github.com/python-trio/trio/pull/1509/
我有一个库想在 FreeBSD 上测试。我的CI设置没有任何 FreeBSD 系统,添加它们会很困难,但是我可以在里面启动一个 VM我的 CI 脚本。 (事实上,我已经这样做来测试更奇特的 Linux 内核版本。)
对于 Linux,这非常简单:从某个发行版站点获取预构建的机器映像,然后使用 cloud-init 注入第一个 运行 脚本,完成。
是否可以用 FreeBSD 做同样的事情?我正在寻找一种自动化的方法来获取标准的 FreeBSD 机器映像(例如从 https://freebsd.org 下载),启动它,然后将程序注入 运行。棘手的部分是它应该是完全自动化的——我不想每次 FreeBSD 发布新版本时都必须手动点击安装程序。
开箱即用,没有像 cloud-init
这样的选项,但您可以创建自己的图像并在 AWS 中使用 firstboot
for example, this script is used to bootstrap a VM with saltstack:
#!/bin/sh
# KEYWORD: firstboot
# PROVIDE: set_hostname
# REQUIRE: NETWORKING
# BEFORE: login
. /etc/rc.subr
name="set_hostname"
rcvar=set_hostname_enable
start_cmd="set_hostname_run"
stop_cmd=":"
export AWS_ACCESS_KEY_ID=key
export AWS_SECRET_ACCESS_KEY=secret
export AWS_DEFAULT_REGION=region
TAG_NAME="Salt"
INSTANCE_ID=$(/usr/local/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id)
REGION=$(/usr/local/bin/curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed 's/.$//')
TAG_VALUE=$(/usr/local/bin/aws ec2 describe-tags --filters "Name=resource-id,Values=${INSTANCE_ID}" "Name=key,Values=$TAG_NAME" --region ${REGION} --output=text | cut -f5)
set_hostname_run()
{
hostname ${INSTANCE_ID}
sysrc hostname="${INSTANCE_ID}"
sysrc salt_minion_enable="YES"
echo ${INSTANCE_ID} > /usr/local/etc/salt/minion_id
pw usermod root -c "root on ${INSTANCE_ID}"
if [ ! -z "${TAG_VALUE}" ]; then
echo "node_type: ${TAG_VALUE}" > /usr/local/etc/salt/grains
fi
service salt_minion start
}
load_rc_config $name
run_rc_command ""
要创建自己的图像,您可以使用此脚本作为起点:https://github.com/fabrik-red/images/blob/master/fabrik.sh#L124, more info here: https://fabrik.red/post/creating-the-image/
你也可以简单的在Virtualbox中安装FreeBSD,配置与firstboot
相关的脚本,测试,当你对结果满意时,导出它,导出前注意/firstboot
存在(touch /firstboot
) 因为在第一次启动后它将被删除,并且在导出后如果不存在它可能不会调用脚本。
创建映像后,您可以多次使用它,无需每次都创建一个新的 "custom" VM,这完全取决于您用于 bootstrap 和加载的脚本"firstboot".
上的脚本要 "inject" 您的软件通常需要能够写入文件系统,而最可靠的方法是 运行 系统本身。换句话说,有一个 FreeBSD VM 来创建 FreeBSD VM - 你可以在本地构建它们(man 7 版本),或者从 http://download.FreeBSD.org 获取 VM 映像,将它们的 rootfs 安装在某个地方,将你的软件放在你需要的任何地方,并且让它从挂载文件系统的 /etc/rc.local.
执行我仔细研究了一下,结果证明这是可能的,虽然很尴尬。
FreeBSD 官方版本分为三种:预装 VM、ISO 安装程序和 U 盘安装程序。
默认情况下,官方预装的 VM 映像不提供任何从外部编写脚本的方式。他们使用 FreeBSD UFS 文件系统,该文件系统无法从任何通用 OS 进行修改。 (Linux 可以以只读方式挂载 UFS,并且有一些用于读写支持的代码,但默认情况下读写支持是禁用的,需要自定义内核。)所以没有简单的方法以编程方式修改它们,除非您已经安装了 FreeBSD。
USB 记忆棒安装程序也使用 UFS 文件系统,所以已经过时了。我发现的预构建 live CD 也是如此,比如 mfsBSD(CD 本身是 iso9660,但它只是一个解压到内存中的大 UFS blob 的容器)。
这样就剩下 CD 安装程序了。事实证明,这些实际上使用 iso9660 作为其实际文件布局。而且我们不需要 FreeBSD 来使用 iso9660!
所以你要做的是:
- 下载 CD 安装程序
- 修改其上的文件以在无需用户交互的情况下进行安装,将一些自定义配置应用于新系统,然后关闭
- 使用您最喜欢的 VM 运行器启动带有空白硬盘驱动器映像的 CD,然后让它 运行 在该硬盘驱动器上安装 FreeBSD
- 启动硬盘,随心所欲。
我忽略了大量繁琐的细节,但这是基本的想法。这里还有一个完整的示例:https://github.com/python-trio/trio/pull/1509/