https://rhinstaller.github.io/anaconda/intro.html
https://github.com/rhinstaller/pykickstart/blob/master/docs/kickstart-docs.rst
台湾鸟哥写的文档 http://linux.vbird.org/linux_enterprise/0120installation.php
centos 6 install http log
192.168.48.137 - - [25/Jan/2016:17:03:21 +0800] "GET /kickstart/78:2b:cb:69:10:f3 HTTP/1.1" 200 1986 "-" "anaconda/13.21.239" "-"
192.168.48.137 - - [25/Jan/2016:17:03:27 +0800] "GET /centos-6/images/updates.img HTTP/1.1" 404 3650 "-" "anaconda/13.21.239" "-"
192.168.48.137 - - [25/Jan/2016:17:03:27 +0800] "GET /centos-6/images/product.img HTTP/1.1" 404 3650 "-" "anaconda/13.21.239" "-"
192.168.48.137 - - [25/Jan/2016:17:03:41 +0800] "GET /centos-6/images/install.img HTTP/1.1" 200 157290496 "-" "anaconda/13.21.239" "-"
192.168.48.137 - - [25/Jan/2016:17:04:26 +0800] "GET /centos-6/.treeinfo HTTP/1.1" 200 338 "-" "urlgrabber/3.9.1" "-"
192.168.48.137 - - [25/Jan/2016:17:04:27 +0800] "GET /centos-6/.treeinfo HTTP/1.1" 200 338 "-" "urlgrabber/3.9.1" "-"
192.168.48.137 - - [25/Jan/2016:17:04:27 +0800] "GET /centos-6/.treeinfo HTTP/1.1" 200 338 "-" "urlgrabber/3.9.1" "-"
192.168.48.137 - - [25/Jan/2016:17:04:27 +0800] "GET /centos-6/repodata/repomd.xml HTTP/1.1" 200 4061 "-" "CentOS (anaconda)/6.7" "-"
192.168.48.137 - - [25/Jan/2016:17:04:27 +0800] "GET /centos-6/repodata/c11b211333eadda7b2e2d0f7fa8ffbf70a1d32d5182babbb43b90427578e2891-primary.sqlite.bz2 HTTP/1.1" 200 4784716 "-" "CentOS (anaconda)/6.7" "-"
192.168.48.137 - - [25/Jan/2016:17:04:28 +0800] "GET /centos-6/repodata/4df092633ebecaeebdd78359a11a3c13f619f22605322e15e5e307beebd8e641-c6-x86_64-comps.xml HTTP/1.1" 200 1233934 "-" "CentOS (anaconda)/6.7" "-"
192.168.48.137 - - [25/Jan/2016:17:04:29 +0800] "GET /centos-6/repodata/repomd.xml HTTP/1.1" 200 4061 "-" "CentOS (anaconda)/6.7" "-"
192.168.48.137 - - [25/Jan/2016:17:04:29 +0800] "GET /centos-6/repodata/c11b211333eadda7b2e2d0f7fa8ffbf70a1d32d5182babbb43b90427578e2891-primary.sqlite.bz2 HTTP/1.1" 200 4784716 "-" "CentOS (anaconda)/6.7" "-"
192.168.48.137 - - [25/Jan/2016:17:04:30 +0800] "GET /centos-6/repodata/4df092633ebecaeebdd78359a11a3c13f619f22605322e15e5e307beebd8e641-c6-x86_64-comps.xml HTTP/1.1" 200 1233934 "-" "CentOS (anaconda)/6.7" "-"
192.168.48.137 - - [25/Jan/2016:17:04:31 +0800] "GET /centos-6/repodata/486d3ee62873814293a1be370640ae9c71863a35c7299eb76739e03369ad0c3f-c6-x86_64-comps.xml.gz HTTP/1.1" 200 224312 "-" "CentOS (anaconda)/6.7" "-"
192.168.48.137 - - [25/Jan/2016:17:04:32 +0800] "GET /centos-6/repodata/486d3ee62873814293a1be370640ae9c71863a35c7299eb76739e03369ad0c3f-c6-x86_64-comps.xml.gz HTTP/1.1" 200 224312 "-" "CentOS (anaconda)/6.7" "-"
192.168.48.137 - - [25/Jan/2016:17:04:37 +0800] "GET /centos-6/repodata/40eeab440905d20a31dd7db33fa8724fba260bcb1047fb6488027b85c22876d2-filelists.sqlite.bz2 HTTP/1.1" 200 6484373 "-" "CentOS (anaconda)/6.7" "-"
centos 7 install http log
192.168.48.136 - - [06/May/2016:15:19:06 +0800] "GET /kickstart/78:2b:cb:69:10:f3 HTTP/1.1" 200 1150 "-" "curl/7.29.0" "-"
192.168.48.136 - - [06/May/2016:15:19:07 +0800] "GET /centos-7/.treeinfo HTTP/1.1" 200 1109 "-" "curl/7.29.0" "-"
192.168.48.136 - - [06/May/2016:15:19:32 +0800] "GET /centos-7/LiveOS/squashfs.img HTTP/1.1" 200 293052416 "-" "curl/7.29.0" "-"
192.168.48.136 - - [06/May/2016:15:19:32 +0800] "GET /centos-7/images/updates.img HTTP/1.1" 404 3650 "-" "curl/7.29.0" "-"
192.168.48.136 - - [06/May/2016:15:19:32 +0800] "GET /centos-7/images/product.img HTTP/1.1" 404 3650 "-" "curl/7.29.0" "-"
192.168.48.122 - - [06/May/2016:15:19:58 +0800] "GET /centos-7/.treeinfo HTTP/1.1" 200 1109 "-" "urlgrabber/3.10" "-"
192.168.48.122 - - [06/May/2016:15:19:58 +0800] "GET /centos-7/repodata/repomd.xml HTTP/1.1" 200 3734 "-" "CentOS (anaconda)/7 yum/3.4.3" "-"
192.168.48.122 - - [06/May/2016:15:19:58 +0800] "GET /centos-7/.treeinfo HTTP/1.1" 200 1109 "-" "urlgrabber/3.10" "-"
192.168.48.122 - - [06/May/2016:15:19:58 +0800] "GET /centos-7/repodata/5e7aa50a6f6811cee0b55013e2b742ef0aec84cdfdd5ae84875117c283e6aad0-primary.xml.gz HTTP/1.1" 200 312815 "-" "CentOS (anaconda)/7 yum/3.4.3" "-"
192.168.48.122 - - [06/May/2016:15:19:58 +0800] "GET /centos-7/repodata/4a04a16ba51071ab8942bc507087ed59cac82e9b22134b322f1452a45b87a1a2-c7-minimal-x86_64-comps.xml.gz HTTP/1.1" 200 3663 "-" "CentOS (anaconda)/7 yum/3.4.3" "-"
192.168.48.122 - - [06/May/2016:15:19:58 +0800] "GET /centos-7/repodata/90e86d06e1784b6846551fbfb92a21711a570eb3ce99ca4916a8a7344c916d58-primary.sqlite.bz2 HTTP/1.1" 200 631308 "-" "CentOS (anaconda)/7 yum/3.4.3" "-"
linux的安装流程 isolinux/vmlinuz -> isolinux/initrd.img -> /init -> /sbin/loader -> imagaes/install.img -> /usr/bin/anaconda
从上面的http下载日志可以看到在下载pxe所指示的kickstart文件以后,系统下载install.img进入安装过程。
centos7
label linux
menu label ^Install CentOS 7
kernel vmlinuz
append initrd=initrd.img inst.stage2=hd:LABEL=CentOS\x207\x20x86_64 quiet
# inst.stage2=hd:LABEL=CentOS\x207\x20x86_64
centos6
label linux
menu label ^Install or upgrade an existing system
menu default
kernel vmlinuz
append initrd=initrd.img
解压initrd.img
file initrd.img
initrd.img: XZ compressed data
mv initrd.img initrd.img.xz
xz --format=lzma initrd.img.xz --decompress
mkdir initrd && cd initrd
cpio -ivdum < ../initrd.img
解压install.img
file install.img
install.img: Squashfs filesystem, little endian, version 4.0, 157290118 bytes, 14956 inodes, blocksize: 131072 bytes, created: Wed Aug 5 05:41:04 2015
使用centos minimal做过安装源参考以下
http://tapira.hatenablog.com/entry/2015/05/26/115637
关于安装过程的监控交互,可以参考cobbler
http://cobbler.github.io/manuals/2.6.0/Appendix/E_-_Anaconda_Monitoring.html
kickstart
%pre
$SNIPPET('pre_anamon')
%post
$SNIPPET('post_anamon')
pre_anamon
#if $str($getVar('anamon_enabled','')) == "1"
curl -o /tmp/anamon "http://$server:$http_port/cobbler/aux/anamon"
python /tmp/anamon --name "$name" --server "$server" --port "$http_port"
#end if
post_anamon
#if $str($getVar('anamon_enabled','')) == "1"
## install anamon script
curl -o /usr/local/sbin/anamon "http://$server:$http_port/cobbler/aux/anamon"
## install anamon system service
curl -o /etc/rc.d/init.d/anamon "http://$server:$http_port/cobbler/aux/anamon.init"
## adjust permissions
chmod 755 /etc/rc.d/init.d/anamon /usr/local/sbin/anamon
test -d /selinux && restorecon /etc/rc.d/init.d/anamon /usr/local/sbin/anamon
## enable the script
chkconfig --add anamon
## configure anamon service
cat << __EOT__ > /etc/sysconfig/anamon
COBBLER_SERVER="$server"
COBBLER_PORT="$http_port"
COBBLER_NAME="$name"
LOGFILES="/var/log/boot.log /var/log/messages /var/log/dmesg /root/ks-post.log"
__EOT__
#end if
anamon
#!/usr/bin/python
"""
This is a script used to automatically log details from an Anaconda
install back to a cobbler server.
Copyright 2008, Red Hat, Inc and Others
various@redhat.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
"""
import os
import sys
import string
import time
import re
import base64
import shlex
# on older installers (EL 2) we might not have xmlrpclib
# and can't do logging, however this is more widely
# supported than remote syslog and also provides more
# detail.
try:
import xmlrpclib
except ImportError, e:
print "xmlrpclib not available, exiting"
sys.exit(0)
# shlex.split support arrived in python-2.3, the following will provide some
# accomodation for older distros (e.g. RHEL3)
if not hasattr(shlex, "split"):
shlex.split = lambda s: s.split(" ")
class WatchedFile:
def __init__(self, fn, alias):
self.fn = fn
self.alias = alias
self.reset()
def reset(self):
self.where = 0
self.last_size = 0
self.lfrag=''
self.re_list={}
self.seen_line={}
def exists(self):
return os.access(self.fn, os.F_OK)
def lookfor(self,pattern):
self.re_list[pattern] = re.compile(pattern,re.MULTILINE)
self.seen_line[pattern] = 0
def seen(self,pattern):
if self.seen_line.has_key(pattern):
return self.seen_line[pattern]
else:
return 0
def changed(self):
if not self.exists():
return 0
size = os.stat(self.fn)[6]
if size > self.last_size:
self.last_size = size
return 1
else:
return 0
def uploadWrapper(self, blocksize = 262144):
"""upload a file in chunks using the uploadFile call"""
retries = 3
fo = file(self.fn, "r")
totalsize = os.path.getsize(self.fn)
ofs = 0
while True:
lap = time.time()
contents = fo.read(blocksize)
size = len(contents)
data = base64.encodestring(contents)
if size == 0:
offset = -1
sz = ofs
else:
offset = ofs
sz = size
del contents
tries = 0
while tries <= retries:
debug("upload_log_data('%s', '%s', %s, %s, ...)\n" % (name, self.alias, sz, offset))
if session.upload_log_data(name, self.alias, sz, offset, data):
break
else:
tries = tries + 1
if size == 0:
break
ofs += size
fo.close()
def update(self):
if not self.exists():
return
if not self.changed():
return
try:
self.uploadWrapper()
except:
raise
class MountWatcher:
def __init__(self,mp):
self.mountpoint = mp
self.zero()
def zero(self):
self.line=''
self.time = time.time()
def update(self):
found = 0
if os.path.exists('/proc/mounts'):
fd = open('/proc/mounts')
while 1:
line = fd.readline()
if not line:
break
parts = string.split(line)
mp = parts[1]
if mp == self.mountpoint:
found = 1
if line != self.line:
self.line = line
self.time = time.time()
fd.close()
if not found:
self.zero()
def stable(self):
self.update()
if self.line and (time.time() - self.time > 60):
return 1
else:
return 0
def anamon_loop():
alog = WatchedFile("/tmp/anaconda.log", "anaconda.log")
alog.lookfor("step installpackages$")
slog = WatchedFile("/tmp/syslog", "sys.log")
xlog = WatchedFile("/tmp/X.log", "X.log")
llog = WatchedFile("/tmp/lvmout", "lvmout.log")
storage_log = WatchedFile("/tmp/storage.log", "storage.log")
prgm_log = WatchedFile("/tmp/program.log", "program.log")
vnc_log = WatchedFile("/tmp/vncserver.log", "vncserver.log")
kcfg = WatchedFile("/tmp/ks.cfg", "ks.cfg")
scrlog = WatchedFile("/tmp/ks-script.log", "ks-script.log")
dump = WatchedFile("/tmp/anacdump.txt", "anacdump.txt")
mod = WatchedFile("/tmp/modprobe.conf", "modprobe.conf")
kspre = WatchedFile("/tmp/ks-pre.log", "ks-pre.log")
# Setup '/mnt/sysimage' watcher
sysimage = MountWatcher("/mnt/sysimage")
# Monitor for {install,upgrade}.log changes
package_logs = list()
package_logs.append(WatchedFile("/mnt/sysimage/root/install.log", "install.log"))
package_logs.append(WatchedFile("/mnt/sysimage/tmp/install.log", "tmp+install.log"))
package_logs.append(WatchedFile("/mnt/sysimage/root/upgrade.log", "upgrade.log"))
package_logs.append(WatchedFile("/mnt/sysimage/tmp/upgrade.log", "tmp+upgrade.log"))
# Monitor for bootloader configuration changes
bootloader_cfgs = list()
bootloader_cfgs.append(WatchedFile("/mnt/sysimage/boot/grub/grub.conf", "grub.conf"))
bootloader_cfgs.append(WatchedFile("/mnt/sysimage/boot/etc/yaboot.conf", "yaboot.conf"))
bootloader_cfgs.append(WatchedFile("/mnt/sysimage/boot/efi/efi/redhat/elilo.conf", "elilo.conf"))
bootloader_cfgs.append(WatchedFile("/mnt/sysimage/etc/zipl.conf", "zipl.conf"))
# Were we asked to watch specific files?
watchlist = list()
waitlist = list()
if watchfiles:
# Create WatchedFile objects for each requested file
for watchfile in watchfiles:
if os.path.exists(watchfile):
watchfilebase = os.path.basename(watchfile)
watchlog = WatchedFile(watchfile, watchfilebase)
watchlist.append(watchlog)
# Use the default watchlist and waitlist
else:
watchlist = [alog, slog, dump, scrlog, mod, llog, kcfg, storage_log, prgm_log, vnc_log, xlog, kspre]
waitlist.extend(package_logs)
waitlist.extend(bootloader_cfgs)
# Monitor loop
while 1:
time.sleep(5)
# Not all log files are available at the start, we'll loop through the
# waitlist to determine when each file can be added to the watchlist
for watch in waitlist:
if alog.seen("step installpackages$") or (sysimage.stable() and watch.exists()):
debug("Adding %s to watch list\n" % watch.alias)
watchlist.append(watch)
waitlist.remove(watch)
# Send any updates
for wf in watchlist:
wf.update()
# If asked to run_once, exit now
if exit:
break
# Establish some defaults
name = ""
server = ""
port = "80"
daemon = 1
debug = lambda x,**y: None
watchfiles = []
exit = False
# Process command-line args
n = 0
while n < len(sys.argv):
arg = sys.argv[n]
if arg == '--name':
n = n+1
name = sys.argv[n]
elif arg == '--watchfile':
n = n+1
watchfiles.extend(shlex.split(sys.argv[n]))
elif arg == '--exit':
exit = True
elif arg == '--server':
n = n+1
server = sys.argv[n]
elif arg == '--port':
n = n+1
port = sys.argv[n]
elif arg == '--debug':
debug = lambda x,**y: sys.stderr.write(x % y)
elif arg == '--fg':
daemon = 0
n = n+1
# Create an xmlrpc session handle
session = xmlrpclib.Server("http://%s:%s/cobbler_api" % (server, port))
# Fork and loop
if daemon:
if not os.fork():
# Redirect the standard I/O file descriptors to the specified file.
DEVNULL = getattr(os, "devnull", "/dev/null")
os.open(DEVNULL, os.O_RDWR) # standard input (0)
os.dup2(0, 1) # Duplicate standard input to standard output (1)
os.dup2(0, 2) # Duplicate standard input to standard error (2)
anamon_loop()
sys.exit(1)
sys.exit(0)
else:
anamon_loop()
anamon.init
#!/bin/bash
## BEGIN INIT INFO
# Provides: anamon
# Default-Start: 3 5
# Default-Stop: 0 1 2 4 6
# Required-Start:
# Should-Start: $network
# Short-Description: Starts the cobbler anamon boot notification program
# Description: anamon runs the first time a machine is booted after
# installation.
## END INIT INFO
#
# anamon: Starts the cobbler post-install boot notification program
#
# chkconfig: 35 99 95
#
# description: anamon runs the first time a machine is booted after
# installation.
#
LOCKFILE="/var/lock/subsys/anamon"
CFGFILE="/etc/sysconfig/anamon"
# Source function library.
. /etc/init.d/functions
# Source anamon config
. $CFGFILE
LOGFILES=${LOGFILES:-/var/log/boot.log}
# FIXME - can we rely on the koan snippet to update /etc/profile.d/cobbler.sh?
if [ -z "$COBBLER_SERVER" ]; then
echo "No COBBLER_SERVER defined in $CFGFILE"
exit 1
fi
if [ -z "$COBBLER_NAME" ]; then
echo "No COBBLER_NAME defined in $CFGFILE"
exit 1
fi
if [ -z "$LOGFILES" ]; then
echo "No LOGFILES defined in $CFGFILE"
exit 1
fi
start() {
echo -n $"Starting anamon: "
daemon /usr/local/sbin/anamon --watchfile \"$LOGFILES\" --name $COBBLER_NAME --server $COBBLER_SERVER --port ${COBBLER_PORT:-80} --exit
RETVAL=$?
[ $RETVAL -eq 0 ] && touch $LOCKFILE
echo
# Disable service start
chkconfig anamon off
return $RETVAL
}
stop () {
echo -n $"Shutting down anamon: "
killproc /usr/local/sbin/anamon
RETVAL=$?
[ $RETVAL -eq 0 ] && rm -f $LOCKFILE
echo
return $RETVAL
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
condrestart)
if [ -f $LOCKFILE ]; then
restart
fi
;;
status)
status anamon
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart}"
RETVAL=2
;;
esac
exit $RETVAL
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
2015-04-28 监控系统 - pnp4nagios