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
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_64centos6
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 ifpost_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 ifanamon
#!/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 posted on 2016-04-28 16:05 北京涛子 阅读( ...) 评论( ...) 编辑 收藏转载于:https://www.cnblogs.com/liujitao79/p/5443028.html