-
Notifications
You must be signed in to change notification settings - Fork 6
/
arch-bootstrap.sh
executable file
·152 lines (130 loc) · 4.74 KB
/
arch-bootstrap.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/bin/bash
#
# arch-bootstrap: Bootstrap a base Arch Linux system.
#
# Dependencies: coreutils, wget, sed, gawk, tar, gzip, chroot, xz.
# Bug tracker: http://code.google.com/p/tokland/issues
# Contact: Arnau Sanchez <tokland@gmail.com>
#
# Install:
#
# $ sudo install -m 755 arch-bootstrap.sh /usr/local/bin/arch-bootstrap
#
# Some examples:
#
# $ sudo arch-bootstrap destination
# $ sudo arch-bootstrap -a x86_64 -r "ftp://ftp.archlinux.org" destination_x86_64
#
# And then you can chroot to the destination directory (default user: root/root):
#
# $ sudo chroot destination
#
set -e -o pipefail -u
# Output to standard error
stderr() { echo "$@" >&2; }
# Output debug message to standard error
debug() { stderr "--- $@"; }
# Extract href attribute from HTML link
extract_href() { sed -n '/<a / s/^.*<a [^>]*href="\([^\"]*\)".*$/\1/p'; }
# Simple wrapper around wget
fetch() { wget -c --passive-ftp --quiet "$@"; }
# Packages needed by pacman (check get-pacman-depenencies.sh)
BASIC_PACKAGES=(acl archlinux-keyring attr bzip2 curl expat glibc gpgme
libarchive libassuan libgpg-error libssh2 openssl pacman pacman-mirrorlist xz zlib)
EXTRA_PACKAGES=(coreutils bash grep gawk file tar initscripts)
PACKDIR="arch-bootstrap"
DEFAULT_REPO_URL="http://mirrors.kernel.org/archlinux"
DEFAULT_ARCH=i686
configure_pacman() {
local DEST=$1; local ARCH=$2
cp "/etc/resolv.conf" "$DEST/etc/resolv.conf"
echo "Server = $REPO_URL/\$repo/os/$ARCH" >> "$DEST/etc/pacman.d/mirrorlist"
}
minimal_configuration() {
local DEST=$1
mkdir -p "$DEST/dev"
echo "root:x:0:0:root:/root:/bin/bash" > "$DEST/etc/passwd"
echo 'root:$1$GT9AUpJe$oXANVIjIzcnmOpY07iaGi/:14657::::::' > "$DEST/etc/shadow"
touch "$DEST/etc/group"
echo "bootstrap" > "$DEST/etc/hostname"
test -e "$DEST/etc/mtab" || echo "rootfs / rootfs rw 0 0" > "$DEST/etc/mtab"
test -e "$DEST/dev/null" || mknod "$DEST/dev/null" c 1 3
test -e "$DEST/dev/random" || mknod -m 0644 "$DEST/dev/random" c 1 8
test -e "$DEST/dev/urandom" || mknod -m 0644 "$DEST/dev/urandom" c 1 9
sed -i "s/^[[:space:]]*\(CheckSpace\)/# \1/" "$DEST/etc/pacman.conf"
sed -i "s/^[[:space:]]*SigLevel[[:space:]]*=.*$/SigLevel = Never/" "$DEST/etc/pacman.conf"
}
check_compressed_integrity() {
local FILEPATH=$1
case "$FILEPATH" in
*.gz) gunzip -t "$FILEPATH";;
*.xz) xz -t "$FILEPATH";;
*) debug "Error: unknown package format: $FILEPATH"
return 1;;
esac
}
uncompress() {
local FILEPATH=$1; local DEST=$2
case "$FILEPATH" in
*.gz) tar xzf "$FILEPATH" -C "$DEST";;
*.xz) xz -dc "$FILEPATH" | tar x -C "$DEST";;
*) debug "Error: unknown package format: $FILEPATH"
return 1;;
esac
}
usage() {
stderr "Usage: $(basename "$0") [-a i686 | x86_64] [-r REPO_URL] DEST"
}
main() {
test $# -eq 0 && set -- "-h"
local ARCH=$DEFAULT_ARCH;
local REPO_URL=$DEFAULT_REPO_URL
while getopts "a:r:h" ARG; do
case "$ARG" in
a) ARCH=$OPTARG;;
r) REPO_URL=$OPTARG;;
*) usage; exit 1;;
esac
done
shift $(($OPTIND-1))
test $# -eq 1 || { usage; exit 1; }
local DEST=$1
local REPO="${REPO_URL%/}/core/os/$ARCH"
debug "core repository: $REPO"
mkdir -p "$PACKDIR"
debug "package directory created: $PACKDIR"
mkdir -p "$DEST"
debug "destination directory created: $DEST"
local LIST_HTML_FILE="$PACKDIR/core_os_$ARCH-index.html"
if ! test -s "$LIST_HTML_FILE"; then
debug "fetch packages list: $REPO/"
# Force trailing '/' needed by FTP servers.
fetch -O "$LIST_HTML_FILE" "$REPO/" ||
{ debug "Error: cannot fetch packages list: $REPO"; exit 1; }
fi
debug "packages HTML index: $LIST_HTML_FILE"
local LIST=$(< "$LIST_HTML_FILE" extract_href | awk -F"/" '{print $NF}' | sort -rn)
test "$LIST" || { debug "Error processing list file: $LIST_HTML_FILE"; exit 1; }
debug "pacman package and dependencies: ${BASIC_PACKAGES[*]}"
for PACKAGE in ${BASIC_PACKAGES[*]}; do
local FILE=$(echo "$LIST" | grep -m1 "^$PACKAGE-[[:digit:]].*\(\.gz\|\.xz\)$")
test "$FILE" || { debug "Error: cannot find package: $PACKAGE"; exit 1; }
local FILEPATH="$PACKDIR/$FILE"
if ! test -e "$FILEPATH" || ! check_compressed_integrity "$FILEPATH"; then
debug "download package: $REPO/$FILE"
fetch -O "$FILEPATH" "$REPO/$FILE"
fi
debug "uncompress package: $FILEPATH"
uncompress "$FILEPATH" "$DEST"
done
debug "configure DNS and pacman"
configure_pacman "$DEST" "$ARCH"
debug "re-install basic packages and install extra packages: ${EXTRA_PACKAGES[*]}"
minimal_configuration "$DEST"
LC_ALL=C chroot "$DEST" /usr/bin/pacman --noconfirm --arch $ARCH \
-Syf ${BASIC_PACKAGES[*]} ${EXTRA_PACKAGES[*]}
# Pacman must be re-configured
configure_pacman "$DEST" "$ARCH"
echo "Done! you can now chroot to the bootstraped system."
}
main "$@"