我不知道这是否可能,但无论如何都要问。
我正在尝试使用 CentOS 7 启动我们的新服务器。到目前为止,我已完成大部分工作,但是出于某种原因,如果我在 Kickstart 脚本的 %pre 部分中使用变量,则它根本无法解析到配置。因此我开始认为这根本不可能?
这是我在 Kickstart 的 %pre 部分中的内容:
%pre --log /tmp/pre-install.log
hostname=serverA120
ip=100.110.120.130
IFS=. read ip1 ip2 ip3 ip4 <<< "$ip"
然后在 Kickstart 期间它应该使用上面填写的信息:
network --bootproto=static --device=eth0 --gateway=100.110.$ip3.1 --ip=$ip --nameserver=1.1.1.1 --netmask=255.255.255.0
network --hostname=$hostname.example.com
并且在 %post 部分我还尝试使用来自 %pre 的变量:
sed -i'' -e '/HOSTNAME=/d' /etc/sysconfig/network
echo HOSTNAME=$hostname.example.com >> /etc/sysconfig/network
echo GATEWAY=100.110.$ip3.1 >> /etc/sysconfig/network
echo BOOTPROTO=static >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo IPADDR=$ip >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo NETMASK=255.255.255.0 >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo BROADCAST=100.110.$ip3.255 >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo NETWORK=100.110.$ip3.0 >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo GATEWAY=100.110.$ip3.1 >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo $hostname.example.com >> /etc/hostname
sudo hostnamectl set-hostname $hostname.example.com
当我无法再访问服务器后,我对 ifcfg-eth0 进行了物理检查,结果显示如下:
IPADDR=
BROADCAST=100.110..255
NETWORK=100.110..0
GATEWAY=100.110..1
我还检查了 /etc/hostname:
$hostname.example.com
因此变量不会被解析到 Kickstart 中。是我做错了什么,还是根本就不可能?有没有其他解决方案?
当然,我可以手动调整前后的所有行,但我想让这尽可能简单,而无需手动编辑所有内容。换句话说,我只需填写 2 行,其余的将按我想要的方式配置。从长远来看,这将使 Kickstarting 多台服务器变得更容易。
我不知道我做错了什么,但检查 ifcfg-eth0 和 hostname 时,它清楚地显示未使用预先输入的变量?但就像我上面说的那样,也许这根本不可能,或者我使用不正确。
不,我不想使用 DHCP 或类似的东西。因为我之后仍然需要手动更改它。我只想在 %pre 中填写前两行(主机名和 ip),并让它在完整安装期间(以及在 %post 中)自动使用。
答案1
您不能将一个块中的变量与另一个块一起使用,因为它们是在不同时间点执行的单独脚本;这些代码段将被拆分并放入单独的文件中,然后按您编写的顺序执行(甚至不按顺序执行),这意味着如果您有 3 个 %pre 段,它们不一定会按顺序执行,所以请记住这一点。此外,您不能将这些变量与 kickstart 的任何其他段一起使用。
一个想法是使用卫星文件来保存你的数据(就像你/tmp/file
在你的文件中写入%pre
然后将其取回你的%post
...那你可以做)
我采用了不同的方法,我实际上为 anaconda 创建了一个完整的诱饵转换,它允许我在磁盘上放置一个假的 kickstart,然后运行一个脚本来用sed 替换或中%%IP%%
的变量。%%HOSTNAME%%
无论如何,您不需要做任何这些,您只需将设置放在块ip1 ip2 ip3 ip4
的顶部%post
,这样您就可以设置变量。
然后您就可以像之前在帖子块中所做的那样简单地编写文件。
跳过 kickstart 中的“网络”行,直接使用network --activate [--device=DEVICENAME]
(如果有多个并且只想使用 1 个,请添加 --device)
以下仅供参考:
当使用 %pre %post 时,您无权访问 BASH,它只是 Bourne shell。
kickstart 允许您在 %pre/%post 行中使用“--interpreter=/bin/bash”,但是在过去经过大量测试之后,我发现它很不稳定并且无法一直正常工作,因此通常我会在块的第一行添加 shebang。
%post --log=/root/post.log
#!/bin/bash
##
[... code ...]
%end
这应该允许您使用 BASH 而不是 Bourne shell。
答案2
我使用类似的方法来获取 dhcp 设置。我希望您可以采取一些额外的步骤来获取静态 IP 地址。
%pre
echo "network --bootproto=dhcp --device=eth0 --ipv6=auto --activate --hostname renameme.ipa.smith122.com" > /tmp/network.ks
for x in $( cat /proc/cmdline );
do
case $x in
SERVERNAME*)
eval $x
echo "network --bootproto=dhcp --device=eth0 --ipv6=auto --activate --hostname ${SERVERNAME}.ipa.example.com" > /tmp/network.ks
;;
NOTIFYEMAIL*)
eval $x
echo "${NOTIFYEMAIL}" > /mnt/sysroot/root/notifyemail.txt
;;
esac
done
然后在 %pre 和 %post 之外,通常在文件中,您需要:
%include /tmp/network.ks
对于你来说,你可能想要一行类似于:
network --bootproto=static --ip=10.0.2.15 --netmask=255.255.255.0 --gateway=10.0.2.254 --nameserver=10.0.2.1
参考
- https://sysadmin.compxtreme.ro/automatically-set-the-hostname-during-kickstart-installation/
- 我自己的博客文章:https://bgstack15.wordpress.com/2019/07/25/use-virt-install-to-fully-automate-the-install-for-centos-fedora-with-kickstart/
- https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/installation_guide/s1-kickstart2-options通过互联网搜索找到
kickstart network
答案3
虽然接受的答案通常是正确的,并且很好地解释了正在发生的事情,但我想补充一些缺失的清晰度,然后展示我正在使用的实际工作实施变化,以演示其中的一些内容。
首先,让我们来强调一下“变量”这一点。%pre
和%post
块只是对任意代码的包装,对安装程序来说毫无意义。它将这些块中的所有内容视为传递给 的简单文本--interpreter
。事实上,您可以使用%pre --interpreter=/bin/sh
和%post --interpreter=/usr/bin/python
,在这种情况下,两个块中的变量甚至在语法上都不兼容。因此,变量“范围”首先%pre/%post
至少是块的本地变量,然后根据选项指定的语言的“范围”规则进一步限制--interpreter
。
现在,接受的答案没有涉及的一个重要点是,该%pre
块在安装环境中执行。安装环境就像一个 live-cd
- 它正在运行 RAM 驻留文件系统。
- 您只能访问安装程序文件系统中包含的命令和实用程序。
- “安装”环境中的设备及其名称可能与“已安装”环境中的设备及其名称不同。
例如,这%pre --log /tmp/pre-install.log
可能不会达到您的预期效果。如果安装程序在启动新安装之前因某种原因安装失败,您可以使用安装程序 shell 访问cat
该文件。但一旦重新启动,写入临时安装程序文件系统的所有内容都将丢失。
而且,从技术上来说这也是不正确的:
一个想法是使用卫星文件来保存你的数据(比如你在 %pre 中写入 /tmp/file 然后将其取回你的 %post... 你可以这样做)
你可以这么做,但是仅有的如果您将其写入在重启后仍能保留的文件系统(如 USB、iSCSI、NFS、CIFS 等),请挂载。
考虑到这一点,在%pre
选择时请遵循 KISS(保持简单...)原则。您可能无法访问更高级的命令/工具/语言;这取决于安装程序包中包含和不包含的内容,并且各种发行版和版本可能会随着时间的推移而改变这一点。
相反,您在块中几乎拥有白卡%post
,因为到那时您将可以访问您在%packages
块中指定的所有内容。
虽然您希望%pre
在所使用的工具和语言方面保持块的简单性,但是使用安装程序命令配置系统的次数越多,您被迫在块中“修补”配置的次数就越少%post
。
工作示例 - 变体
在配置新主机时,我首先收集和/或生成三项内容(出于本示例的目的);MAC 地址、IP 地址、主机名。如果我有大量这些信息,它们通常会进入配置电子表格。下一步是在 DHCP 中创建预留,将裸机或虚拟 MAC 连接到其分配的 IP。然后,IP 和主机名进入 DNS 正向和反向查找区域。您可以使用电子表格中的公式来生成 DHCP 和 DNS 条目,因此它变成了一个剪切和过去的练习。完成 DHCP 和 DNS 后,您只需通过网络启动该框,正确的配置就会发生。我发现 DHCP 预留是为部署甚至重新部署服务器实例的一致性和效率付出的很小代价。
这是 kickstart 文件,它已被精简为仅剩相关条目
#version=RHEL8
text
%include /tmp/network.ks
eula --agreed
reboot
skipx
%pre
#!/bin/bash
DEVICE=$(ip r|grep default|grep -oP '(?<=dev )\S*')
declare -A value
while IFS= read -r line; do
kvp=${line##DHCP4.OPTION\[*\]:*[ ][ ]}
value+=([${kvp% = *}]=${kvp#* = })
done <<< $(nmcli -f dhcp4 device show $DEVICE)
echo "network --device link --bootproto static --ip ${value[ip_address]} --netmask ${value[subnet_mask]} --gateway ${value[routers]} --hostname ${value[host_name]}.${value[domain_name]} --nameserver ${value[domain_name_servers]} --onboot yes --noipv6" > /tmp/network.ks
%end
%post --log=/root/install-post.log
cat << EOF >> /etc/hosts
$(hostname -i) $(hostname -s) $(hostname -f)
EOF
%end
由于我已经为要使用的“静态”配置创建了 DHCP 预留,因此在%pre
块中我用来nmcli
获取相关的 DHCP 参数并使用它们动态生成network...
安装程序要使用的命令。然后,该动态生成的文件将包含在 kickstart 脚本的主体中。
这里可能有点令人困惑的一件事是使用 来$DEVICE
查询dhcp4
参数,但我使用的是network --device link ...
。原因是安装程序设备(我需要查询)与已安装系统中的网络设备名称之间存在差异,我没有通过指定“第一个活动链接”来强制执行这一点,并允许安装程序根据自己的需要命名设备。过去,我曾遇到过麻烦,因为我假设安装程序环境中的活动名称与已安装环境中的名称相同……然后事情就变得一团糟了。
在%post
块中,我做了一件命令无法完成的事情network...
,即将 IP 和主机名添加到 hosts 文件中。如果在%post
块执行时所有先前步骤都已正确配置系统,那么您可以直接从正在运行的配置中获取所需的任何内容……您不需要保留任何变量,%pre
因为此时系统将依靠它们运行。