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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
|
#!/bin/sh
# ArchDistrobox - Craig Jennings <craigmartinjennings@gmail.com>
# License: GNU GPLv3
# Commentary
#
# This script sets up an Arch Linux distrobox setup for software development.
#
# There are two levels of errors:
# * CRASH: Issues that will halt forward progress, aborting this script.
# * ERROR: Issues not serious enough to halt the script.
# Both are printed on screen and in the $logfile.
# Stderr is also printed to the $logfile for all relevant info.
#
# # Code
# uncomment to stop on any error
# set -e
### Constants
username=cjennings
dotfiles_repo="https://git.cjennings.net/dotfiles"
dotemacs_repo="https://git.cjennings.net/dotemacs.git"
dotfiles_home="/home/$username/.dotfiles"
# aur/git source directories go here, logs go in base directiory
source_dir="/home/$username/.local/src"
logfile="$source_dir/archdistrobox-$(date +'%Y-%m-%d-%H-%M-%S').log"
packages_before="$source_dir/archdistrobox-preexisting-package-list.txt"
packages_after="/$source_dir/archdistrobox-post-install-package-list.txt"
archdistrobox_packages="$source_dir/archdistrobox-installed-packages.txt"
### Intro
intro() {
printf "\n\nArchDistrobox launched @ %s\n" "$(date +'%D %T')"| tee -a "$logfile"
STARTTIME=$(date +%s)
errors_encountered=0
# Check that we're not root; error and exit if we are
if [ $(id -u) -eq 0 ]; then
echo "Please do not run this script as root or using sudo!"
exit 1
fi
# on fresh distrobox, $source_dir may not exist yet
[ -d "$source_dir" ] || mkdir "$source_dir" ]
# begin with a clean logfile
[ -f "$logfile" ] && rm -f "$logfile"
touch "$logfile"
# count the arch packages before install
pacman -Q > "$packages_before" || \
error "crash" "generating pre-install package list" "$?"
}
### General Functions
# Error
error () {
# $1 = type ERROR, noted but the script will continue to run.
# anything else will produce CRASH, which halts the script
# $2 = what was happening (e.g., "adding $username to group $groupname")
# $3 = the error code (i.e., "$?")
errors_encountered=$((errors_encountered+1))
case "$1" in
"error")
printf "ERROR: %s failed with error code %s @ %s\n" \
"$2" "$3" "$(date +'%T')" | tee -a "$logfile"
return 1;
;;
*)
printf "CRASH: %s failed with error: %s @ %s. Script halted.\n" \
"$2" "$3" "$(date +'%T')" | tee -a "$logfile"
exit 1;
;;
esac
}
# Display
display () {
# $1 = type (TITLE, ACTION)
# $2 = description (answers: "what are you trying to do?")
case "$1" in
"title")
printf "\n##### %s\n" "$2" | tee -a "$logfile"
return 1;
;;
"subtitle")
printf "\n%s\n" "$2" | tee -a "$logfile"
;;
"task")
printf "...%s @ %s\n" "$2" "$(date +'%T')" | tee -a "$logfile"
return 1;
;;
*)
printf "CRASH: display () called with incorrect arguments.\n"
printf "...called %s type, %s action @ %s\n" \
"$1" "$2" "$(date +'%T')" | tee -a "$logfile"
exit 1;
;;
esac
}
# Pacman Install
pacman_install() {
action="installing $1 via pacman" && display "task" "$action"
if ! (sudo pacman --noconfirm --needed -S "$1" >> "$logfile" 2>&1); then
action="retrying $1" && display "task" "$action"
if ! (sudo pacman --noconfirm --needed -S "$1" >> "$logfile" 2>&1); then
action="retrying $1 once more" && display "task" "$action"
(sudo pacman --noconfirm --needed -S "$1" >> "$logfile" 2>&1) ||
error "error" "$action" "$?"
fi
fi
}
# AUR Install
aur_install() {
action="installing $1 via the AUR" && display "task" "$action"
if ! (yay -S --noconfirm "$1" >> "$logfile" 2>&1); then
action="retrying $1" && display "task" "$action"
if ! (yay -S --noconfirm "$1" >> "$logfile" 2>&1); then
action="retrying $1 once more" && display "task" "$action"
(yay -S --noconfirm "$1" >> "$logfile" 2>&1) ||
error "error" "$action" "$?"
fi
fi
}
# PIP Install
pip_install() {
[ -x "$(command -v "pip")" ] || pacman_install python-pip
action="installing $1 via PIP" && display "task" "$action"
(yes | pip install "$1" >> "$logfile" 2>&1) || \
error "error" "$action" "$?"
}
### Prerequisites
prerequisites() {
# why these software packages are 'required'
# base_devel - required tools to compile
# coreutils - comparing package lists
# curl - to transfer source code
# git - tools required to work with git source respositories
# go - required to build yay, the aur installer
# python - required for python pip installs
# stow - places dotfiles (see: https://bit.ly/41GmysO)
# tar - extract unix archives
# vi - should things go wrong, we'll need an editor
# zsh - we need a shell interpreter for yay; this one's mine
display "title" "Prerequisites"
# display "subtitle" "Bootstrapping"
# action="refreshing the package cache" && display "task" "$action"
# (pacman -Syu --noconfirm >> "$logfile" 2>&1) || error "crash" "$action" "$?"
display "subtitle" "Required Software"
for software in base-devel coreutils curl git go python \
stow tar vi zsh; do
pacman_install "$software"
done
}
### User Customizations
# user_customizations() {
# Change cjennings's shell to zsh
chsh -s $(which zsh)
# Pull relevant dotfiles and put them in their proper place
# -----------------------------------------------------
# action="User Customizations" && display "title" "$action"
# action="cloning dotfiles" && display "task" "$action"
# (git clone --depth 1 $dotfiles_repo "$dotfiles_home" \
# >> "$logfile" 2>&1) || error "error" "$action" "$?"
# action="moving dotfiles into place" && display "task" "$action"
# (cd "$dotfiles_home" && stow --no-folding --adopt * \
# >> "$logfile" 2>&1 ) || error "error" "$action" "$?"
# action="restoring dotfile versions" && display "task" "$action"
# (cd "$dotfiles_home" && git restore . \
# >> "$logfile" 2>&1 ) || error "error" "$action" "$?"
# }
### AUR Installer
aur_installer () {
display "title" "AUR Installer"
yay_repo="https://aur.archlinux.org/yay.git"
build_dir="$source_dir/yay"
display "task" "creating yay build directory"
if ! (mkdir -p "$build_dir" >> "$logfile" 2>&1); then
error "crash" "creating yay build directory"
fi
display "task" "fetching source code for yay"
if ! (git clone --depth 1 "$yay_repo" "$build_dir" >> "$logfile" 2>&1); then
error "error" "cloning source code for yay"
(cd "$build_dir" && git pull --force origin master >> "$logfile" 2>&1) || \
error "crash" "changing directories to $build_dir and pulling source code" "$?"
fi
action="packaging and installing yay"; display "task" "$action"
(cd "$build_dir" && makepkg --noconfirm -si >> "$logfile" 2>&1) || \
error "crash" "$action" "$?"
}
### Desktop Environment
environment_tools() {
display "title" "Environment Tools"
# System Utilities
action="System Utilities" && display "subtitle" "$action"
pacman_install dmidecode
pacman_install dosfstools
pacman_install exfat-utils
pacman_install lshw
pacman_install ntfs-3g
pacman_install sshfs
pacman_install testdisk
pacman_install udisks2
aur_install downgrade
aur_install inxi
# File Associations
action="File/Application Associations" && display "subtitle" "$action"
pacman_install perl-file-mimeinfo
pacman_install xdg-utils
# Authentication Tools
action="Authentication Tools" && display "subtitle" "$action"
pacman_install gnupg
pacman_install polkit
pacman_install gnome-keyring
# ensure correct permissions on .gpg directory
# the colon means the user's group will have perms
[ -d /home/"$username"/.gnupg ] || mkdir /home/"$username"/.gnupg
chown -R "$username": /home/"$username"/.gnupg
find /home/"$username"/.gnupg -type f -exec chmod 600 {} \;
find /home/"$username"/.gnupg -type d -exec chmod 700 {} \;
# Command Line Utilities
action="Command Line Utilities" && display "subtitle" "$action"
for software in htop mc ncdu tmux fzf zip unzip atool wget detox \
lsof usbutils moreutils; do
pacman_install "$software"
done;
for software in task-spooler speedtest-go gotop-bin rar; do
aur_install "$software"
done;
# Help And Documentation
action="Help and Documentation" && display "subtitle" "$action"
pacman_install man
pacman_install arch-wiki-docs
pacman_install tealdeer
aur_install cht.sh-git
}
### Developer Workstation
developer_workstation () {
action="Developer Workstation" && display "title" "$action"
action="Programming Languages and Utilities" && display "subtitle" "$action"
# C
pacman_install clang # C/C++ compiler
pacman_install cmake # make system
pacman_install gdb # the GNU debugger
pacman_install splint # C programming static analysis
pacman_install valgrind # memory management utility
# java
pacman_install jdk-openjdk # Java Development Kit
pacman_install openjdk-doc # ...and the documentation
# Lisps
pacman_install guile # GNU Scheme
pacman_install sbcl # Steel Bank Common Lisp
pacman_install racket # Racket + SICP mit-scheme emulation
# Rust
pacman_install rust # Rust programming language
# Python
pacman_install pyright # Python language server
pacman_install pyenv # Python environment manager
# Shell
pacman_install shellcheck # Shell script linter
pacman_install shfmt # Shell script formatter
# Go
pacman_install delve # Go programming language debugger
pacman_install go-tools # Go language utilities
pacman_install gopls # Go language server
pacman_install staticcheck # Go programming language linter
# Typescript
pacman_install jq # JSON processor
pacman_install typescript # Typescript programming language
pacman_install nodejs # Node-js JavaScript runtime environment
pacman_install npm # Node-js package manager
aur_install nvm # Node-js version manager
# HTML
pacman_install tidy # HTML formatter
pacman_install prettier # Multi-language formatter
# General Utilities
pacman_install meld # Visual diff
pacman_install ripgrep # Fast grep utility
aur_install the_silver_searcher # Another fast grep utility
action="Programming Editors" && display "subtitle" "$action"
pacman_install mg
pacman_install neovim
}
emacs_install() {
action="Emacs Dependencies" && display "subtitle" "$action"
pacman_install emacs
# supporting utilities used by my emacs configuration
aur_install exercism-bin # command line tool for exercism.io
aur_install isync # email sync
aur_install mu # email indexer and utilities
aur_install multimarkdown # markdown conversion
aur_install proselint # grammar checker
aur_install gist # command-line gist poster
pacman_install aspell # spell check system
pacman_install aspell-en # spell check english files
pacman_install fd # a faster find for dired/dirvish
pacman_install ffmpegthumbnailer # video previews in dired/dirvish
pacman_install imagemagick # image previews for dired/dirvish
pacman_install libgccjit # native compilation for Emacs
pacman_install mediainfo # generating media info in dired/dirvish
pacman_install mpv # video viewer
pacman_install mailutils # Emacs' IMAP mail support backend
pacman_install msmtp # mail transport for Mu4e
pacman_install msmtp-mta # mail transport for Mu4e
pacman_install python-lsp-server # python language support
pacman_install rlwrap # adds readline support to programs (SBCL-related)
pacman_install sdcv # stardict dictionary system
pacman_install yt-dlp # video download
action="setting up emacs configuration files" && display "task" "$action"
(git clone --recurse-submodules $dotemacs_repo "/home/$username/.emacs.d" >> \
"$logfile" 2>&1) || error "error" "$action" "$?"
action="Android Utilities" && display "subtitle" "$action"
pacman_install android-file-transfer
pacman_install android-tools
action="DevOps Utilities" && display "subtitle" "$action"
action="installing devops virtualization and automation tools" && display "task" "$action"
pacman_install vagrant
pacman_install ansible
# Docker within Podman!
pacman_install docker
pacman_install docker-compose
action="adding user to docker group" && display "task" "$action"
(gpasswd -a $username docker >> "$logfile" 2>&1) || error "error" "$action" "$?"
action="enabling docker service to launch on boot" && display "task" "$action"
systemctl enable docker.service >> "$logfile" 2>&1 || error "error" "$action" "$?"
}
### Supplemental Software
supplemental_software() {
display "title" "Supplemental Software"
# pacman installs
pacman_install aria2 # fast downloader
pacman_install code # visual studio code
pacman_install dash # posix compliant /bin/sh
pacman_install dfc # better display of available space on mounted filesystems
pacman_install docx2txt # recovers text from docx files
pacman_install entr # run arbitrary commands when files change
pacman_install figlet # words into ascii art
pacman_install filezilla # ftp gui
pacman_install gparted # disk partition utility
pacman_install gucharmap # gui display of character maps
pacman_install gzip # compression tool
pacman_install libconfig # library for processing structured config files
pacman_install mosh # alt SSH terminal with roaming and responsiveness support
pacman_install neofetch # cli system information tool
pacman_install odt2txt # converts from open document to text
pacman_install p7zip # p7zip compression tool
pacman_install pandoc # universal document converter
pacman_install poppler-glib # poppler-glib document viewer library
pacman_install pv # monitor progress of data through pipeline
pacman_install ranger # terminal file manager
pacman_install rclone # syncs files from gdrive, s3, dropbox, etc.
pacman_install texlive-meta # latex
pacman_install w3m # text based browser
pacman_install xz # general purpose data compression tool
pacman_install zathura # document viewer
pacman_install zathura-cb # zathura plugin for comics
pacman_install zathura-djvu # zathura plugin for djvu books
pacman_install zathura-pdf-mupdf # zathura plugin for pdf
pacman_install zlib # compression library
# aur installs
aur_install dtrx # extraction tool
aur_install figlet-fonts # fonts for figlet
aur_install hfsprogs # file system tools for Mac OS
aur_install mcomix # image viewer for comic books
aur_install nsxiv # image viewer
aur_install shell-gpt # gpt in your terminal
aur_install snore-git # sleep with feedback
aur_install tageditor # metadata editor for mkv, webm and related video files
aur_install zsh-fast-syntax-highlighting-git # Optimized and extended zsh-syntax-highlighting
# git installs
git_install https://github.com/clamiax/snore.git # sleep with feedback
}
### Distrobox Exports
distrobox_exports() {
for software in emacs \
filezilla \
gparted \
meld \
code ; do
distrobox-export --app "$software"
done
}
### Outro
outro() {
display "subtitle" "Statistics"
action="identifying newly installed packages" && display "task" "$action"
pacman -Q > "$packages_after" || error "error" "$action" "$?"
(comm -13 --nocheck-order "$packages_before" "$packages_after" > "$archdistrobox_packages") || \
error "error" "$action" "$?"
action="comparing timestamps" && display "task" "$action"
ENDTIME=$(date +%s)
totalsecs=$(($ENDTIME - $STARTTIME))
mins=$(($totalsecs / 60))
secs=$(($totalsecs % 60))
new_packages=$(cat $archdistrobox_packages | wc -l)
printf "\n"
printf "Completion time : %s\n" "$(date +'%D %T')" | tee -a "$logfile"
printf "Elapsed time : %s minutes, %s seconds\n" $mins $secs | tee -a "$logfile"
printf "Errors encountered : %s\n" $errors_encountered | tee -a "$logfile"
printf "Log file location : %s\n" "$logfile"
printf "Packages installed : %s\n" "$new_packages"
printf "\n"
printf "Please reboot before working with your new workstation.\n\n"
}
### Installation Steps
intro
prerequisites
# user_customizations
aur_installer
environment_tools
developer_workstation
emacs_install
supplemental_software
distrobox_exports
outro
exit 0
|