使用 virt-install initrd-inject 预置命令字符串因换行符而失败

使用 virt-install initrd-inject 预置命令字符串因换行符而失败

我正在使用 libvirt 的 virt-install 命令创建一个新的虚拟机。该命令使用 initrd-inject 从虚拟机管理程序中提取本地预置文件:

virt-install \
--autostart \
--name vm1 \
--ram 4096 \
--location=http://archive.ubuntu.com/ubuntu/dists/precise/main/installer-amd64/ \
--initrd-inject=/var/lib/libvirt/preseeds/vms/preseed.cfg \
--extra-args="locale=en_US console-setup/ask_detect=false keyboard-configuration/layoutcode=us hostname=virtual domain=unassigned-domain interface=auto" \
--vcpu=4 \
--vnc \
--vnclisten=0.0.0.0 \
--noautoconsole \
--os-type=linux \
--os-variant=ubuntukarmic \
-w bridge=br0 \
-w bridge=br1 \
-w network=default \
 --disk format=qcow2,size=20,bus=virtio,path=/export/vm/vm1.qcow2

一切工作正常,直到 preseed 的 late_command 部分动态地将 upstart 脚本打印到文件中,内容如下行;

d-i preseed/late_command string printf "description \"the run-once bootstrap\"\n\nstart on net-device-up\nstop on runlevel [!2345]\n\npre-start script\n wget -O /root/bootstrap.sh http://my.bootstrap/bootstrap;\nchmod +x /root/bootstrap.sh;\n  /root/bootstrap.sh > /var/log/bootstrap.log 2>&1\nend script" > /target/etc/init/run_bootstrap.conf

虚拟机的 Ubuntu 12.04 安装程序停止,我在安装程序调试日志中看到以下信息:

Feb 21 19:44:54 preseed: running preseed command preseed/late_command: printf "description \"the run-once bootstrap\"
Feb 21 19:44:54 log-output: sh: syntax error: unterminated quoted string
Feb 21 19:44:54 finish-install: /bin/preseed_command: return: line 23: Illegal number: start
Feb 21 19:44:54 finish-install: warning: /usr/lib/finish-install.d/07preseed returned error code 2

preseed 的语法没问题,因为它在 extra-args 行中通过 http 正确运行,而不是通过 initrd-inject。双引号也正确转义,因为即使删除它们,问题仍然存在。

我的虚拟机管理程序是 debian-squeeze,其 virtinst=0.600.3-3 是从 sid 中​​挑选出来的。

答案1

据我所知:反斜杠是预置文件格式中换行符的转义字符。如果您需要在 shell 命令中出现反斜杠,我发现的唯一解决方案是对所需的值进行 base64 编码。例如,如果您需要自定义 rc.local,并且不想使用“wget”获取它(或者不能,因为在安装后环境中没有 DNS 配置,如 18.04 中),您可以对脚本进行编码:

$ base64 < my-rc.local | tr -d \\n

然后,你的预种子应该包含:

ubiquity ubiquity/success_command string echo your_base64_encoded_file | base64 -d > /target/etc/rc.local ; chmod +x /target/etc/rc.local

(我必须经过艰难的过程才能学会这一点。)

相关内容