Discuss

Installnetbuildpackerpe(2)

minlearn 仲裁员
板块:通用举报

把DI当online packer用:利用installnet制作一个云装机packerpe(2)

本文关键字:自建udeb站镜像。local repository debian installer preseed,Preseed install from local repository,start http server in a preseed file,debian中用NC+SHELL实现的一个web服务,浏览器装机,Preseed failed with exit 2,d-i preseed/early_command string stuck hang,linux grep -o 只匹配字串

继把Debianinstaller当online packer用文章1,本文继续讲解生成packerpe。

给前面的脚本增加和镜像格式判断,统一wget和dd progress

增强主要是为了pipecmdstr处整合,稍后会看到(因此也顺便支持了onelist,oneindex这种网盘外链作为ddurl地址,其实质是302跳转体)。这段替换前文的cd /tmp/boot;到echo -e "Downloading kernel : ${LinuxMirror}/....../debian-installer/amd64/initrd.gz"间的内容:

LIBC6_SUPPORT='pool/main/g/glibc/libc6_2.28-10_amd64.deb'
declare -A SHARED_SUPPORT
SHARED_SUPPORT=(
["webfs1"]="pool/main/g/gnutls28/libgnutls30_3.6.7-4+deb10u3_amd64.deb"
["webfs2"]="pool/main/p/p11-kit/libp11-kit0_0.23.15-2_amd64.deb"
["webfs3"]="pool/main/libt/libtasn1-6/libtasn1-6_4.13-3_amd64.deb"
["webfs4"]="pool/main/n/nettle/libnettle6_3.4.1-1_amd64.deb"
["webfs5"]="pool/main/n/nettle/libhogweed4_3.4.1-1_amd64.deb"
["webfs6"]="pool/main/g/gmp/libgmp10_6.1.2+dfsg-4_amd64.deb"

["webfs7"]="pool/main/libf/libffi/libffi6_3.2.1-9_amd64.deb"
["webfs8"]="pool/main/m/mime-support/mime-support_3.62_all.deb"
["webfs9"]="pool/main/libu/libunistring/libunistring2_0.9.10-1_amd64.deb"

["wgetssl7"]="pool/main/libi/libidn2/libidn2-0_2.0.5-1+deb10u1_amd64.deb"
["wgetssl8"]="pool/main/libp/libpsl/libpsl5_0.20.2-2_amd64.deb"
["wgetssl9"]="pool/main/p/pcre2/libpcre2-8-0_10.32-5_amd64.deb"
["wgetssl10"]="pool/main/u/util-linux/libuuid1_2.33.1-0.1_amd64.deb"
["wgetssl11"]="pool/main/z/zlib/zlib1g_1.2.11.dfsg-1_amd64.deb"
)

HTTPD_SUPPORT='pool/main/w/webfs/webfs_1.21+ds1-12_amd64.deb'
WGETSSL_SUPPORT='pool/main/w/wget/wget_1.20.1-1.1_amd64.deb'
DDPROGRESS_SUPPORT='pool/main/b/busybox/busybox_1.30.1-4_amd64.deb'
UNZIP=''
DDURL=''

[[ -n "$LIBC6_SUPPORT" ]] && {
  echo -ne 'Add libc6 support(binary-amd64/Package)...'

  wget --no-check-certificate -qO ${LIBC6_SUPPORT##*/} $LinuxMirror/$LIBC6_SUPPORT; \
  ar x ${LIBC6_SUPPORT##*/} data.tar.xz; xz -d data.tar.xz; tar xf data.tar; \
  rm -rf data.tar ${LIBC6_SUPPORT##*/}

  [[ ! -f  /tmp/boot/lib/x86_64-linux-gnu/libc.so.6 ]] && echo 'Error! LIBC6_SUPPORT.' && exit 1 || sleep 3s && echo -en "[\033[32mok\033[0m]\n" ;
  # [[ $? -eq '0' ]] && echo -ne 'Success! \n\n'
}

[[ -n "$HTTPD_SUPPORT" ]] && {
  echo -ne 'Add httpd and httpd shared support(binary-amd64/Package)...'

  wget --no-check-certificate -qO ${HTTPD_SUPPORT##*/} $LinuxMirror/$HTTPD_SUPPORT; \
  ar x ${HTTPD_SUPPORT##*/} data.tar.xz; xz -d data.tar.xz; tar xf data.tar; \
  rm -rf data.tar ${HTTPD_SUPPORT##*/}

  for pkg in $(echo "${!SHARED_SUPPORT[@]}" |sed 's/\ /\n/g' |sort -n |grep "^webfs")
    do
      CurPkg="${SHARED_SUPPORT[$pkg]}"
      [ -n "$CurPkg" ] || continue

      wget --no-check-certificate -qO ${CurPkg##*/} $LinuxMirror/$CurPkg; \
      ar x ${CurPkg##*/} data.tar.xz; xz -d data.tar.xz; tar xf data.tar; \
      rm -rf data.tar ${CurPkg##*/}
    done

  [[ ! -f  /tmp/boot/usr/bin/webfsd ]] && echo 'Error! HTTPD_SUPPORT.' && exit 1 || sleep 3s && echo -en "[\033[32mok\033[0m]\n" ;
  # [[ $? -eq '0' ]] && echo -ne 'Success! \n\n'
}

if [[ -n "$tmpDDURL" ]]; then
  echo -ne 'setting final ddurl and prepare unzip mode...'
  echo "$tmpDDURL" |grep -q '^http://\|^ftp://\|^https://';
  [[ $? -ne '0' ]] && echo 'No valid URL in the DD argument,Only support http://, ftp:// and https:// !' && exit 1;

  IMGHEADER="$(curl -Is "$tmpDDURL")";
  IMGTYPE="$(echo "$IMGHEADER" | grep -E -o 'raw|qcow2|gzip|x-gzip|301|302')" || IMGTYPE='0';
# [[ "$IMGTYPE" -ne '0' ]] && echo 'not a raw,tar,gunzip or 301/302 ref file, exit ... !' && exit 1 || {

    [[ "$IMGTYPE" == 'raw' ]] && UNZIP='0' && DDURL="$tmpDDURL" && sleep 3s && echo -en "[\033[32m raw \033[0m]\n";
    [[ "$IMGTYPE" == 'qcow2' ]] && UNZIP='0' && DDURL="$tmpDDURL" && sleep 3s && echo -en "[\033[32m raw \033[0m]\n";
    [[ "$IMGTYPE" == 'gzip' ]] && UNZIP='1' && DDURL="$tmpDDURL" && sleep 3s && echo -en "[\033[32m gzip \033[0m]\n";
    [[ "$IMGTYPE" == 'x-gzip' ]] && UNZIP='1' && DDURL="$tmpDDURL" && sleep 3s && echo -en "[\033[32m x-gzip \033[0m]\n";
    [[ "$IMGTYPE" == 'gunzip' ]] && UNZIP='2' && DDURL="$tmpDDURL" && sleep 3s && echo -en "[\033[32m gunzip \033[0m]\n";

    [[ "$IMGTYPE" == '302' ]] && IMGHEADERCHECKPASS2="$(echo "$IMGHEADER" |grep 'Location: http'|sed 's/Location: //g')" && IMGHEADERCHECKPASS2=${IMGHEADERCHECKPASS2%$'\r'} && IMGHEADERCHECKPASS3="$(curl -Is "$IMGHEADERCHECKPASS2" |grep 'content-location: http'|sed 's/content-location: //g')" && IMGHEADERCHECKPASS3=${IMGHEADERCHECKPASS3%$'\r'} && IMGTYPECHECKPASS2="$(curl -Is "$IMGHEADERCHECKPASS3" | grep -E -o 'raw|qcow2|gzip|x-gzip|gunzip')" && {
      [[ "$IMGTYPECHECKPASS2" == 'raw' ]] && UNZIP='0' && DDURL="$tmpDDURL" && sleep 3s && echo -en "[\033[32m raw \033[0m]\n";
      [[ "$IMGTYPECHECKPASS2" == 'qcow2' ]] && UNZIP='0' && DDURL="$tmpDDURL" && sleep 3s && echo -en "[\033[32m raw \033[0m]\n";
      [[ "$IMGTYPECHECKPASS2" == 'gzip' ]] && UNZIP='1' && DDURL="$tmpDDURL" && sleep 3s && echo -en "[\033[32m gzip \033[0m]\n";
      [[ "$IMGTYPECHECKPASS2" == 'x-gzip' ]] && UNZIP='1' && DDURL="$tmpDDURL" && sleep 3s && echo -en "[\033[32m x-gzip \033[0m]\n";
      [[ "$IMGTYPECHECKPASS2" == 'gunzip' ]] && UNZIP='2' && DDURL="$tmpDDURL" && sleep 3s && echo -en "[\033[32m gunzip \033[0m]\n";
    }

    [[ "$IMGTYPE" == '0' ]] && echo 'not a raw,tar,gunzip or 301/302 ref file, exit ... !' && exit 1;
# }

else
  echo 'Please input vaild image URL! ';
  exit 1;
fi

#echo "$DDURL" |grep -q '^https://'
#[[ $? -eq '0' ]] && {

  [[ -n "$WGETSSL_SUPPORT" ]] && {
    echo -ne 'always Add wgetssl and wgetssl support(binary-amd64/Package)...'

    wget --no-check-certificate -qO ${WGETSSL_SUPPORT##*/} $LinuxMirror/$WGETSSL_SUPPORT; \
    ar x ${WGETSSL_SUPPORT##*/} data.tar.xz; xz -d data.tar.xz; tar xf data.tar; \
    rm -rf data.tar ${WGETSSL_SUPPORT##*/}; mv -f /tmp/boot/usr/bin/wget /tmp/boot/usr/bin/wget2

    for pkg in $(echo "${!SHARED_SUPPORT[@]}" |sed 's/\ /\n/g' |sort -n |grep "^wgetssl")
      do
        CurPkg="${SHARED_SUPPORT[$pkg]}"
        [ -n "$CurPkg" ] || continue

        wget --no-check-certificate -qO ${CurPkg##*/} $LinuxMirror/$CurPkg; \
        ar x ${CurPkg##*/} data.tar.xz; xz -d data.tar.xz; tar xf data.tar; \
        rm -rf data.tar ${CurPkg##*/}
      done

    [[ ! -f  /tmp/boot/usr/bin/wget2 ]] && echo 'Error! WGETSSL_SUPPORT.' && exit 1 || sleep 3s && echo -en "[\033[32mok\033[0m]\n" ;
    # sed -i 's/wget\ -qO-/\/usr\/bin\/wget2\ --no-check-certificate\ --retry-connrefused\ --tries=7\ --continue\ -qO-/g' /tmp/boot/preseed.cfg
    # [[ $? -eq '0' ]] && echo -ne 'Success! \n\n'
  }
    # || {
    # echo -ne 'Not wgetssl support package! \n\n';
    # exit 1;
    # }
#}

[[ -n "$DDPROGRESS_SUPPORT" ]] && {
  echo -ne 'Add ddprogress support(binary-amd64/Package)...'

  wget --no-check-certificate -qO ${DDPROGRESS_SUPPORT##*/} $LinuxMirror/$DDPROGRESS_SUPPORT; \
  ar x ${DDPROGRESS_SUPPORT##*/} data.tar.xz; xz -d data.tar.xz; tar xf data.tar; \
  rm -rf data.tar ${DDPROGRESS_SUPPORT##*/}

  [[ ! -f  /tmp/boot/bin/busybox ]] && echo 'Error! DDPROGRESS_SUPPORT.' && exit 1 || sleep 3s && echo -en "[\033[32mok\033[0m]\n" ;
  # [[ $? -eq '0' ]] && echo -ne 'Success! \n\n'
}

如果你发现启动不了文件系统出现制作文件系统时出现的那些错误,那就是可能glibc低了。注意到dd status progress我并未在接下的preseed中用到。

整合精简几大件,the net, the loader, the preseed file

下面是脚本的继续,准备net设置,grub loader和preseed file供打包:

sleep 5s

echo -e "\n\033[36m# Preparing others\033[0m\n"

echo -e "the net"

setNet='0'
interface=''

[ -n "$ipAddr" ] && [ -n "$ipMask" ] && [ -n "$ipGate" ] && setNet='1';
[[ -n "$tmpWORD" ]] && myPASSWORD="$(openssl passwd -1 "$tmpWORD")";
[[ -z "$myPASSWORD" ]] && myPASSWORD='$1$4BJZaD0A$y1QykUnJ6mXprENfwpseH0';

if [[ -n "$interface" ]]; then
  IFETH="$interface"
else
  IFETH="auto"
fi

[[ "$setNet" == '1' ]] && {
  IPv4="$ipAddr";
  MASK="$ipMask";
  GATE="$ipGate";
} || {
  DEFAULTNET="$(ip route show |grep -o 'default via [0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.*' |head -n1 |sed 's/proto.*\|onlink.*//g' |awk '{print $NF}')";
  [[ -n "$DEFAULTNET" ]] && IPSUB="$(ip addr |grep ''${DEFAULTNET}'' |grep 'global' |grep 'brd' |head -n1 |grep -o '[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}/[0-9]\{1,2\}')";
  IPv4="$(echo -n "$IPSUB" |cut -d'/' -f1)";
  NETSUB="$(echo -n "$IPSUB" |grep -o '/[0-9]\{1,2\}')";
  GATE="$(ip route show |grep -o 'default via [0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}' |head -n1 |grep -o '[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}')";
  [[ -n "$NETSUB" ]] && MASK="$(echo -n '128.0.0.0/1,192.0.0.0/2,224.0.0.0/3,240.0.0.0/4,248.0.0.0/5,252.0.0.0/6,254.0.0.0/7,255.0.0.0/8,255.128.0.0/9,255.192.0.0/10,255.224.0.0/11,255.240.0.0/12,255.248.0.0/13,255.252.0.0/14,255.254.0.0/15,255.255.0.0/16,255.255.128.0/17,255.255.192.0/18,255.255.224.0/19,255.255.240.0/20,255.255.248.0/21,255.255.252.0/22,255.255.254.0/23,255.255.255.0/24,255.255.255.128/25,255.255.255.192/26,255.255.255.224/27,255.255.255.240/28,255.255.255.248/29,255.255.255.252/30,255.255.255.254/31,255.255.255.255/32' |grep -o '[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}'${NETSUB}'' |cut -d'/' -f1)";
}

[[ -n "$GATE" ]] && [[ -n "$MASK" ]] && [[ -n "$IPv4" ]] || {
  echo "Not found \`ip command\`, It will use \`route command\`."

  ipNum() {
    local IFS='.';
    read ip1 ip2 ip3 ip4 <<<"$1";
    echo $((ip1*(1<<24)+ip2*(1<<16)+ip3*(1<<8)+ip4));
  }

  SelectMax(){
  ii=0;
  for IPITEM in `route -n |awk -v OUT=$1 '{print $OUT}' |grep '[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}'`
    do
      NumTMP="$(ipNum $IPITEM)";
      eval "arrayNum[$ii]='$NumTMP,$IPITEM'";
      ii=$[$ii+1];
    done
  echo ${arrayNum[@]} |sed 's/\s/\n/g' |sort -n -k 1 -t ',' |tail -n1 |cut -d',' -f2;
  }

  [[ -z $IPv4 ]] && IPv4="$(ifconfig |grep 'Bcast' |head -n1 |grep -o '[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}' |head -n1)";
  [[ -z $GATE ]] && GATE="$(SelectMax 2)";
  [[ -z $MASK ]] && MASK="$(SelectMax 3)";

  [[ -n "$GATE" ]] && [[ -n "$MASK" ]] && [[ -n "$IPv4" ]] || {
    echo "Error! Not configure network. ";
    exit 1;
  }
}

[[ "$setNet" != '1' ]] && [[ -f '/etc/network/interfaces' ]] && {
  [[ -z "$(sed -n '/iface.*inet static/p' /etc/network/interfaces)" ]] && AutoNet='1' || AutoNet='0';
  [[ -d /etc/network/interfaces.d ]] && {
    ICFGN="$(find /etc/network/interfaces.d -name '*.cfg' |wc -l)" || ICFGN='0';
    [[ "$ICFGN" -ne '0' ]] && {
      for NetCFG in `ls -1 /etc/network/interfaces.d/*.cfg`
        do 
          [[ -z "$(cat $NetCFG | sed -n '/iface.*inet static/p')" ]] && AutoNet='1' || AutoNet='0';
          [[ "$AutoNet" -eq '0' ]] && break;
        done
    }
  }
}

[[ "$setNet" != '1' ]] && [[ -d '/etc/sysconfig/network-scripts' ]] && {
  ICFGN="$(find /etc/sysconfig/network-scripts -name 'ifcfg-*' |grep -v 'lo'|wc -l)" || ICFGN='0';
  [[ "$ICFGN" -ne '0' ]] && {
    for NetCFG in `ls -1 /etc/sysconfig/network-scripts/ifcfg-* |grep -v 'lo$' |grep -v ':[0-9]\{1,\}'`
      do 
        [[ -n "$(cat $NetCFG | sed -n '/BOOTPROTO.*[dD][hH][cC][pP]/p')" ]] && AutoNet='1' || {
          AutoNet='0' && . $NetCFG;
          [[ -n $NETMASK ]] && MASK="$NETMASK";
          [[ -n $GATEWAY ]] && GATE="$GATEWAY";
        }
        [[ "$AutoNet" -eq '0' ]] && break;
      done
  }
}

echo -e "the loader"

LoaderMode='0'
setInterfaceName='0'
setIPv6='0'

if [[ "$LoaderMode" == "0" ]]; then
  [[ -f '/boot/grub/grub.cfg' ]] && GRUBVER='0' && GRUBDIR='/boot/grub' && GRUBFILE='grub.cfg';
  [[ -z "$GRUBDIR" ]] && [[ -f '/boot/grub2/grub.cfg' ]] && GRUBVER='0' && GRUBDIR='/boot/grub2' && GRUBFILE='grub.cfg';
  [[ -z "$GRUBDIR" ]] && [[ -f '/boot/grub/grub.conf' ]] && GRUBVER='1' && GRUBDIR='/boot/grub' && GRUBFILE='grub.conf';
  [ -z "$GRUBDIR" -o -z "$GRUBFILE" ] && echo -ne "Error! \nNot Found grub.\n" && exit 1;
else
  tmpINSTANTWITHOUTVNC='0'
fi

if [[ "$LoaderMode" == "0" ]]; then
  [[ ! -f $GRUBDIR/$GRUBFILE ]] && echo "Error! Not Found $GRUBFILE. " && exit 1;

  [[ ! -f $GRUBDIR/$GRUBFILE.old ]] && [[ -f $GRUBDIR/$GRUBFILE.bak ]] && mv -f $GRUBDIR/$GRUBFILE.bak $GRUBDIR/$GRUBFILE.old;
  mv -f $GRUBDIR/$GRUBFILE $GRUBDIR/$GRUBFILE.bak;
  [[ -f $GRUBDIR/$GRUBFILE.old ]] && cat $GRUBDIR/$GRUBFILE.old >$GRUBDIR/$GRUBFILE || cat $GRUBDIR/$GRUBFILE.bak >$GRUBDIR/$GRUBFILE;
else
  GRUBVER='2'
fi


[[ "$GRUBVER" == '0' ]] && {
  READGRUB='/tmp/grub.read'
  cat $GRUBDIR/$GRUBFILE |sed -n '1h;1!H;$g;s/\n/%%%%%%%/g;$p' |grep -om 1 'menuentry\ [^{]*{[^}]*}%%%%%%%' |sed 's/%%%%%%%/\n/g' >$READGRUB
  LoadNum="$(cat $READGRUB |grep -c 'menuentry ')"
  if [[ "$LoadNum" -eq '1' ]]; then
    cat $READGRUB |sed '/^$/d' >/tmp/grub.new;
  elif [[ "$LoadNum" -gt '1' ]]; then
    CFG0="$(awk '/menuentry /{print NR}' $READGRUB|head -n 1)";
    CFG2="$(awk '/menuentry /{print NR}' $READGRUB|head -n 2 |tail -n 1)";
    CFG1="";
    for tmpCFG in `awk '/}/{print NR}' $READGRUB`
      do
        [ "$tmpCFG" -gt "$CFG0" -a "$tmpCFG" -lt "$CFG2" ] && CFG1="$tmpCFG";
      done
    [[ -z "$CFG1" ]] && {
      echo "Error! read $GRUBFILE. ";
      exit 1;
    }

    sed -n "$CFG0,$CFG1"p $READGRUB >/tmp/grub.new;
    [[ -f /tmp/grub.new ]] && [[ "$(grep -c '{' /tmp/grub.new)" -eq "$(grep -c '}' /tmp/grub.new)" ]] || {
      echo -ne "\033[31mError! \033[0mNot configure $GRUBFILE. \n";
      exit 1;
    }
  fi
  [ ! -f /tmp/grub.new ] && echo "Error! $GRUBFILE. " && exit 1;
  sed -i "/menuentry.*/c\menuentry\ \'Packer PE \[debian\ jessie\ amd64\]\'\ --class debian\ --class\ gnu-linux\ --class\ gnu\ --class\ os\ \{" /tmp/grub.new
  sed -i "/echo.*Loading/d" /tmp/grub.new;
  INSERTGRUB="$(awk '/menuentry /{print NR}' $GRUBDIR/$GRUBFILE|head -n 1)"
}

[[ "$GRUBVER" == '1' ]] && {
  CFG0="$(awk '/title[\ ]|title[\t]/{print NR}' $GRUBDIR/$GRUBFILE|head -n 1)";
  CFG1="$(awk '/title[\ ]|title[\t]/{print NR}' $GRUBDIR/$GRUBFILE|head -n 2 |tail -n 1)";
  [[ -n $CFG0 ]] && [ -z $CFG1 -o $CFG1 == $CFG0 ] && sed -n "$CFG0,$"p $GRUBDIR/$GRUBFILE >/tmp/grub.new;
  [[ -n $CFG0 ]] && [ -z $CFG1 -o $CFG1 != $CFG0 ] && sed -n "$CFG0,$[$CFG1-1]"p $GRUBDIR/$GRUBFILE >/tmp/grub.new;
  [[ ! -f /tmp/grub.new ]] && echo "Error! configure append $GRUBFILE. " && exit 1;
  sed -i "/title.*/c\title\ \'DebianNetboot \[jessie\ amd64\]\'" /tmp/grub.new;
  sed -i '/^#/d' /tmp/grub.new;
  INSERTGRUB="$(awk '/title[\ ]|title[\t]/{print NR}' $GRUBDIR/$GRUBFILE|head -n 1)"
}

if [[ "$LoaderMode" == "0" ]]; then
  [[ -n "$(grep 'linux.*/\|kernel.*/' /tmp/grub.new |awk '{print $2}' |tail -n 1 |grep '^/boot/')" ]] && Type='InBoot' || Type='NoBoot';

  LinuxKernel="$(grep 'linux.*/\|kernel.*/' /tmp/grub.new |awk '{print $1}' |head -n 1)";
  [[ -z "$LinuxKernel" ]] && echo "Error! read grub config! " && exit 1;
  LinuxIMG="$(grep 'initrd.*/' /tmp/grub.new |awk '{print $1}' |tail -n 1)";
  [ -z "$LinuxIMG" ] && sed -i "/$LinuxKernel.*\//a\\\tinitrd\ \/" /tmp/grub.new && LinuxIMG='initrd';

  if [[ "$setInterfaceName" == "1" ]]; then
    Add_OPTION="net.ifnames=0 biosdevname=0";
  else
    Add_OPTION="";
  fi

  if [[ "$setIPv6" == "1" ]]; then
    Add_OPTION="$Add_OPTION ipv6.disable=1";
  fi

  BOOT_OPTION="auto=true $Add_OPTION hostname=debian domain= -- quiet"

  [[ "$Type" == 'InBoot' ]] && {
    sed -i "/$LinuxKernel.*\//c\\\t$LinuxKernel\\t\/boot\/vmlinuz $BOOT_OPTION" /tmp/grub.new;
    sed -i "/$LinuxIMG.*\//c\\\t$LinuxIMG\\t\/boot\/initrd.img" /tmp/grub.new;
  }

  [[ "$Type" == 'NoBoot' ]] && {
    sed -i "/$LinuxKernel.*\//c\\\t$LinuxKernel\\t\/vmlinuz $BOOT_OPTION" /tmp/grub.new;
    sed -i "/$LinuxIMG.*\//c\\\t$LinuxIMG\\t\/initrd.img" /tmp/grub.new;
  }

  sed -i '$a\\n' /tmp/grub.new;
fi

[[ "$tmpINSTANTWITHOUTVNC" == '0' ]] && {
  GRUBPATCH='0';

  if [[ "$LoaderMode" == "0" ]]; then
  [ -f '/etc/network/interfaces' -o -d '/etc/sysconfig/network-scripts' ] || {
    echo "Error, Not found interfaces config.";
    exit 1;
  }

  sed -i ''${INSERTGRUB}'i\\n' $GRUBDIR/$GRUBFILE;
  sed -i ''${INSERTGRUB}'r /tmp/grub.new' $GRUBDIR/$GRUBFILE;
  [[ -f  $GRUBDIR/grubenv ]] && sed -i 's/saved_entry/#saved_entry/g' $GRUBDIR/grubenv;
  fi

  cd /tmp/boot;
  COMPTYPE="gzip";
  CompDected='0'
  for ListCOMP in `echo -en 'gzip\nlzma\nxz'`
    do
      if [[ "$COMPTYPE" == "$ListCOMP" ]]; then
        CompDected='1'
        if [[ "$COMPTYPE" == 'gzip' ]]; then
          NewIMG="initrd.img.gz"
        else
          NewIMG="initrd.img.$COMPTYPE"
        fi
        mv -f "/boot/initrd.img" "/tmp/$NewIMG"
        break;
      fi
    done
  [[ "$CompDected" != '1' ]] && echo "Detect compressed type not support." && exit 1;
  [[ "$COMPTYPE" == 'lzma' ]] && UNCOMP='xz --format=lzma --decompress';
  [[ "$COMPTYPE" == 'xz' ]] && UNCOMP='xz --decompress';
  [[ "$COMPTYPE" == 'gzip' ]] && UNCOMP='gzip -d';

  $UNCOMP < /tmp/$NewIMG | cpio --extract --verbose --make-directories --no-absolute-filenames >>/dev/null 2>&1

  echo -e "the preseed"

  [[ "$UNZIP" == '0' ]] && PIPECMDSTR='wget2 --no-check-certificate -qO- '$DDURL' |dd of=$(list-devices disk |head -n1)';
  [[ "$UNZIP" == '1' ]] && PIPECMDSTR='wget2 --no-check-certificate -qO- '$DDURL' |tar zOx |dd of=$(list-devices disk |head -n1)';
  [[ "$UNZIP" == '2' ]] && PIPECMDSTR='wget2 --no-check-certificate -qO- '$DDURL' |gzip -dc |dd of=$(list-devices disk |head -n1)';

cat >/tmp/boot/preseed.cfg<<EOF
d-i preseed/early_command string anna-install

d-i debian-installer/locale string en_US
d-i console-setup/layoutcode string us

d-i keyboard-configuration/xkb-keymap string us

d-i hw-detect/load_firmware boolean true

d-i netcfg/choose_interface select $IFETH
d-i netcfg/disable_autoconfig boolean true
d-i netcfg/dhcp_failed note
d-i netcfg/dhcp_options select Configure network manually
# d-i netcfg/get_ipaddress string $ipAddr
d-i netcfg/get_ipaddress string $IPv4
d-i netcfg/get_netmask string $MASK
d-i netcfg/get_gateway string $GATE
d-i netcfg/get_nameservers string 8.8.8.8
d-i netcfg/no_default_route boolean true
d-i netcfg/confirm_static boolean true

d-i mirror/country string manual
#d-i mirror/http/hostname string $IPv4
d-i mirror/http/hostname string httpredir.debian.org
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string

# webfsd -i $IPv4 -p 80 -r /var/log/ -l /var/log/httpd.log

d-i apt-setup/services-select multiselect
d-i debian-installer/allow_unauthenticated boolean true

d-i passwd/root-login boolean ture
d-i passwd/make-user boolean false
d-i passwd/root-password-crypted password $myPASSWORD
d-i user-setup/allow-password-weak boolean true
d-i user-setup/encrypt-home boolean false

d-i clock-setup/utc boolean true
d-i time/zone string US/Eastern
d-i clock-setup/ntp boolean true

d-i partman/early_command string $PIPECMDSTR; /sbin/reboot
EOF

  [[ "$LoaderMode" != "0" ]] && AutoNet='1'

  [[ "$setNet" == '0' ]] && [[ "$AutoNet" == '1' ]] && {
    sed -i '/netcfg\/disable_autoconfig/d' /tmp/boot/preseed.cfg
    sed -i '/netcfg\/dhcp_options/d' /tmp/boot/preseed.cfg
    sed -i '/netcfg\/get_.*/d' /tmp/boot/preseed.cfg
    sed -i '/netcfg\/confirm_static/d' /tmp/boot/preseed.cfg
  }

  #[[ "$GRUBPATCH" == '1' ]] && {
  #  sed -i 's/^d-i\ grub-installer\/bootdev\ string\ default//g' /tmp/boot/preseed.cfg
  #}
  #[[ "$GRUBPATCH" == '0' ]] && {
  #  sed -i 's/debconf-set\ grub-installer\/bootdev.*\"\;//g' /tmp/boot/preseed.cfg
  #}

  sed -i '/user-setup\/allow-password-weak/d' /tmp/boot/preseed.cfg
  sed -i '/user-setup\/encrypt-home/d' /tmp/boot/preseed.cfg
  #sed -i '/pkgsel\/update-policy/d' /tmp/boot/preseed.cfg
  #sed -i 's/umount\ \/media.*true\;\ //g' /tmp/boot/preseed.cfg

  [[ -f '/boot/firmware.cpio.gz' ]] && {
    gzip -d < /boot/firmware.cpio.gz | cpio --extract --verbose --make-directories --no-absolute-filenames >>/dev/null 2>&1
  }

注意上面的脚本中输出至preseed file至EOF止的内容必须顶格写,Ks.cf是installment.sh用来用同样ubuntu支持preseed支持centos的方法。已删,在文件中,我注释了原来使用内置的webfsd服务器作镜像的方案,因为preseed early command string中欠入webfsd启动命令(放anna install前),会导致PE启动时early command运行时,umount时前台却在加载webfsd卡住,需要ctrlc才能继续,但实际上webfsd已成功运行。

所以我将注释webfsd的逻辑放在preseed中某位置,这个位置是它应该启动时的时机。实际上early command string中都不比它合适。未来想办法让它以正确方式起作用。

打包

  sleep 5s

  echo -e "\n\033[36m# Packaging \033[0m\n"

  find . | cpio -H newc --create --quiet | gzip -9 > /boot/initrd.img;
  [[ "$tmpINSTANTWITHOUTVNC" == '0' ]] &&  echo "finished, auto reboot after 30s...(if needed, you can press ctrl c to interrupt to bak the /boot/initrd.img, then manually reboot to continue)";sleep 30s

  rm -rf /tmp/boot;

}

[[ "$tmpINSTANTWITHOUTVNC" == '1' ]] && {
  sed -i '$i\\n' $GRUBDIR/$GRUBFILE
  sed -i '$r /tmp/grub.new' $GRUBDIR/$GRUBFILE
  echo -e "\n\033[33m\033[04mIt will reboot! \nPlease connect VNC! \nSelect\033[0m\033[32m Packer PE [debian jessie amd64] \033[33m\033[4mto install system.\033[04m\n\n\033[31m\033[04mThere is some information for you.\nDO NOT CLOSE THE WINDOW! \033[0m\n"
  echo -e "\033[35mIPv4\t\tNETMASK\t\tGATEWAY\033[0m"
  echo -e "\033[36m\033[04m$IPv4\033[0m\t\033[36m\033[04m$MASK\033[0m\t\033[36m\033[04m$GATE\033[0m\n\n"

  read -n 1 -p "Press Enter to reboot..." INP
  [[ "$INP" != '' ]] && echo -ne '\b \n\n';
}

chown root:root $GRUBDIR/$GRUBFILE
chmod 444 $GRUBDIR/$GRUBFILE


if [[ "$LoaderMode" == "0" ]]; then
  sleep 3 && reboot >/dev/null 2>&1
else
  rm -rf "$HOME/loader"
  mkdir -p "$HOME/loader"
  cp -rf "/boot/initrd.img" "$HOME/loader/initrd.img"
  cp -rf "/boot/vmlinuz" "$HOME/loader/vmlinuz"
  [[ -f "/boot/initrd.img" ]] && rm -rf "/boot/initrd.img"
  [[ -f "/boot/vmlinuz" ]] && rm -rf "/boot/vmlinuz"
  echo && ls -AR1 "$HOME/loader"
fi

脚本结束。

——

这个脚本还有其它很多需要增强的地方,比如dd progress显示。还比如改成了生成双分区。保留packerpe到第一分区。整盘其实可以preseed/partman成二个分区,一个分区200M放生成的packerpe自身(未来,还可以在这个packerpe集成dbcolinux或集成linuxbpot,coreboot,clover等),

还比如,扩展镜像到整个磁盘空间,实际上windows通过ntfs fuse是实现了的。对于linux磁盘,要处理镜像分区表适配到目标整个磁盘。这不光适用于dd方案。也适用于将磁盘打包成dd镜像(脚本中改变pipecmdstr,镜像扩容缩容)。然后nc 监听,供其它机器下载其镜像或直接dd。这是这个脚本的反向功能。

还比如,利用webfsd的cgi改dd地址。也可用grub的auto url变换dd地址。Ddurl参数保留到下一次。且读取位置不再在preseed中。

但是我不想做了,以后继续吧。这些天做windows server 2019 core的dd镜像也较累了,用了跟做osx云镜像差不多的方法:在linuxkvm中套虚拟机。


(此处不设回复,扫码到微信参与留言,或直接点击到原文)

minlearn.org,tg: minlearn_1keydd,本人长期接有偿付费dd。不会D的,和要定制镜像的都可以t我