Thank you for writing and maintaining this great piece of software. I haven't spent much time playing with pacui yet, so I'm not very familiar with all its features. One feature that I really like is the "edit config files" option. Would it be possible to add a feature to this submenu to en masse create backups of all those config files with a .bak extension. That would be a super handy feature to have in case you ever needed to restore a config file that was altered. If it is a lot effort to implement then don't bother, (but if it' can easily be done) it would be a nice feature to have. Thanks again for this great piece of coding.
for inspiration (if required),
I have a script of this type, saved in a.gz archive all .conf (if different date from the original package = I modified them) and files in xxx.d/ plus some home files
#!/usr/bin/env bash
pkgname='config-save'
version=0.1.0-1
# test in asset function
unset DEVELOPER PARAMS ADMIN CONFIG VERBOSE LOCAL DIR PACKAGES
#PARAMS=1
DEVELOPER=1
PACKAGES=1
DIR=1
LOCAL=1
#general install directories
declare -A DIRS=()
DIRS[local]="$HOME/.config/${pkgname}.conf"
DIRS[save]="/tmp/$pkgname"
error_file="/tmp/$pkgname.err"
#########################
function usage()
{
echo -e "Usage: $pkgname
-g --git : save in repo git
-z --gz : save in archive\n
-p --package : only packages
-l --local : only locale config ~/.config/${pkgname}.conf
-d --dir : only files /etc/*.d/*\n
-v --verbose : show more information\n"
echo -e "output in : ${DIRS[save]}/"
}
# call one error : cp zozoleb 2> $error_file
#(( $? )) && error "oops"
function error()
{
local msg=$1
[[ -f "$error_file" ]] && {
msg="${msg}: $(head -n1 $error_file)"
rm $error_file
}
echo "${msg}" >&2
}
function asset()
{
local E_PARAM_ERR=98
local E_ASSERT_FAILED=99
((PARAMS)) && {
(( $# < 1 )) && {
error "expected argument"
usage
exit $E_PARAM_ERR
}
}
((ADMIN)) && {
(($EUID != 0)) && {
error "you cannot perform this operation unless you are root."
exit $E_ASSERT_FAILED
}
}
((CONFIG)) && {
[ -r "${DIRS[conf]}" ] || {
error "config file not found \"${DIRS[conf]}\""
exit $E_ASSERT_FAILED
}
}
}
function init_paths()
{
DIRS[local]="$HOME/.config/${pkgname}.conf"
DIRS[path]=''
DIRS[conf]="/etc/${pkgname}.conf"
DIRS[lib]="/usr/lib/${pkgname}"
DIRS[doc]="/usr/share/doc/${pkgname}"
local lg=$(locale 2>/dev/null | awk -F'=' '/^LANG/ {print $2}')
DIRS[conf.lang]=${lg:0:2}
DIRS[dico]="/usr/share/locale/${DIRS[conf.lang]}/LC_MESSAGES/$pkgname"
}
##########################################################
# PROJECT FUNCTIONS
##########################################################
function packages.save()
{
pacman -Qqen > "${DIRS[save]}/pkglist-repo.txt"
pacman -Qqem > "${DIRS[save]}/pkglist-aur.txt"
printf "saved in %s\n" ${DIRS[save]}
}
function package.findconf()
{
#find all conf file in one package
local package="${1-:'pacman'}"
local f
date_p=$(date -d "$(LANG=C pacman -Qi ${package} | awk -F':' '/Install Date/ {print $2}')" +%s)
((VERBOSE)) && echo "package $package installed le : ${date_p} : $(LANG=C pacman -Qi ${package} | awk -F':' '/Install Date/ {print $2}')"
for f in $(pacman -Qlq "${package}" | grep "/etc/" | grep -v "/$"); do
[ -f "$f" ] || continue
#echo "get date for ${f}"
local date_m=$(stat -c %Y "${f}")
#date_f=$(/usr/bin/date -r "$f" +%s) bug :(
if (( $date_m - $date_p > 500 )); then
echo -e "\t-- $f is to save .... $date_p <> $date_m"
echo "$f" >> ${DIRS[save.diff]}
else
((VERBOSE)) && echo -e "\t-- $date_p == $date_m , $f is original !"
fi
done
}
function packages.findconf()
{
local pkg
echo "------------------------------"
echo "-- all packages"
while read pkg
do
package.findconf "$pkg"
done < "${DIRS[save]}/pkglist-repo.txt"
}
function add_diff() {
local f="$1"
if [ -f "$f" ]; then
echo "$f" >> ${DIRS[save.diff]}
echo -e "\t\t$f (add)"
fi
}
function d.findconf()
{
local dir="${1-:'/etc/systemd/journald.conf.d'}"
local f
((VERBOSE)) && echo -e "\t${dir} (DIR)"
for f in ${dir}/*; do
[ -d "$f" ] && continue
[ -f "$f" ] || continue
((VERBOSE)) && echo -e "\t\t$f"
#local pkg=$(pacman -Qoq "$f" 2>/dev/null)
# if file not in one package SAVE
if (! pacman -Qoq "$f" &>/dev/null); then
add_diff "$f"
fi
done
}
function ds.findconf()
{
echo "------------------------------"
echo "-- all .d directories"
for d in $(find /etc/ -type d -iname "*.d" -readable 2>/dev/null); do
d.findconf "$d"
done
}
function list.findconf()
{
local dir="${1-:'/etc/systemd/journald.conf.d'}"
local f
if [ -d "$dir" ]; then
((VERBOSE)) && echo -e "\t$dir DIR"
for f in ${dir}/*; do
[ -d "$f" ] && list.findconf "$f" # continue
[ -f "$f" ] || continue
add_diff "$f"
done
else
add_diff "$dir"
fi
}
function lists.findconf()
{
echo "------------------------------"
list.findconf "/etc/issue"
list.findconf "/etc/locale.conf"
list.findconf "/etc/pacman.conf"
list.findconf "$HOME/.bashrc"
list.findconf "$HOME/.bash_profile"
list.findconf "$HOME/.zshrc"
list.findconf "$HOME/.yaourtrc"
list.findconf "$HOME/.nanorc"
list.findconf "$HOME/.gitconfig"
list.findconf "$HOME/.config/user-dirs.dirs"
list.findconf "$HOME/.config/autostart"
echo "-- all files and directories in ~/.config/${pkgname}.conf"
while read f
do
list.findconf "$f"
done < "${DIRS[local]}"
}
function git.create()
{
local url=${1:-'https://gitlab.com/$LOGIN/arch-save.git'}
git init
git remote add origin $url
}
function git.save()
{
# git add, commit, git push NEXT
echo "------------------------------"
}
function save.create()
{
local f
# lire fichier "${DIRS[save]}/etc.list"
# copier les fichiers dans "${DIRS[save.diff]}"
echo "------------------------------"
#cat "${DIRS[save.diff]}"
echo "-- cp all files in ${DIRS[save.diff]}"
while read f
do
[ -f "$f" ] || continue
[ -r "$f" ] || continue # pas les droits en lecture !
((VERBOSE)) && echo "copy of $f in\t${DIRS[save]}${f}"
install -pD "$f" "${DIRS[save]}$f"
done < "${DIRS[save.diff]}"
}
function save.gz()
{
# gzip directory "${DIRS[save]}"
echo "------------------------------"
echo "-- create archive in ${DIRS[save]}"
local namef="$(hostname -s)-$(lsb_release -i | awk '{print $3}')-$(date +%F).tar.gz"
namef=${namef,,}
cd "${DIRS[save]}"
rm "${DIRS[save]}/${namef}" 2>/dev/null
tar -czf "/tmp/${namef}" -C "${DIRS[save]}" "."
mv "/tmp/${namef}" "${DIRS[save]}/${namef}"
echo "archive: ${DIRS[save]}/${namef}"
}
##########################################################
# RUN
##########################################################
run()
{
rm -rf "${DIRS[save]}" &>/dev/null
[ -d "${DIRS[save]}" ] || mkdir "${DIRS[save]}"
DIRS[save.diff]="${DIRS[save]}/etc.list"
echo ''> "${DIRS[save.diff]}"
packages.save
((PACKAGES)) && packages.findconf
((DIR)) && ds.findconf
((LOCAL)) && lists.findconf
save.create
#((GIT)) && git.save
((GZ)) && save.gz
}
main()
{
# load home conf
init_paths
SHORT=hvgzldpu:
LONG=help,verbose,git,gz,local,dir,packages,url
PARSED=$(getopt --options $SHORT --longoptions $LONG --name "$0" -- "$@")
(( $? != 0 )) && exit 1
eval set -- "$PARSED"
while true; do
case "$1" in
-g|--git)
GIT=1
shift
;;
-z|--gz)
GZ=1
shift
;;
-v|--verbose)
VERBOSE=1
shift
;;
-u|--url)
URL="$2"
shift
;;
-d|--dir)
unset PACKAGES LOCAL
shift
;;
-p|--package)
unset LOCAL DIR
shift
;;
-l|--local)
unset PACKAGES DIR
shift
;;
-h|--help)
usage
exit 0
;;
--)
shift
break
;;
*)
echo "Programming error"
exit 3
;;
esac
done
#ARGS=("$@")
unset LONG SHORT PARSED
# tests
asset "$@"
#run
run "$@"
}
if [ "${BASH_SOURCE[0]}" == "$0" ]; then
main "$@"
exit 0
else
export -f packages.save
fi
BUT
old script (with dates compare) ; best way its to use pacman -kk
sudo LANG=C pacman -Qkk 2>1| grep -oE '\/.*Modification time ' | cut -d'(' -f1
sudo tar -cvzf my-system-config.tar.gz $( LANG=C pacman -Qkk 2>1| grep -oE '\/.*Modification time ' | cut -d'(' -f1)
Very nice.
if you want to create a backup of your config files, i recommend to create a git
repository like this:
sudo pacman -S git
- <go to the directory you want to create your git repo, e.g. to
/etc/
> git init
-
git add .
(add all files to be tracked by git. alternatively, you can only track individual files or track all files except for some (google for ".gitignore")) git commit -m "first backup"
every time you want to save your config files, you can do another commit.
if you want to get rid of all git backups simply delete the .git
folder.
git
is much more flexible than all the stuff i could integrate in pacui.
I use fix-pacman-errors to update mirrors, but the last time I used it, it deleted my user configurations, so I couldn't log to Manjaro anymore, and I had to do a fresh install.
Thank you for that!
the only commands, which can remove files from your system in the "fix pacman errors" option are:
sudo rm -r /tmp/pacui*
sudo unlink "/var/lib/pacman/db.lck
sudo rm -r /etc/pacman.d/gnupg
as you can see, your configuration files in your user (i.e. home) directory are untouched. therefore, i conclude that your following statement is false:
the only case, in which people were not be able to login into manjaro anymore after using pacui, is when the "maintain system" option was used. here an exemplary case:
tl;dr: It is highly likely you have experienced the same. In this case, you have to thank your (probably) unknowing past self for deleting your /etc/shadow, /etc/passed
, and /etc/group
files (which included your login password and other essential stuff) and replacing them with *.pacnew
files, despite a nice diff view of what you were going to delete.
you likely meant these thanks in an ironic way, but i take them literally.
pacui does not stop you from breaking your system - but it let's you do it efficiently.
This is why I love pacui
I think it is very much within the spirit of manjaro and arch based Linux in general
I couldn't even use advanced options in boot menu to be able to use maintain-system option.
I just don't know how deleting the current user could be a good way to fix errors!
I didn't pay too much attention to the message, and I chose overwrite, but I didn't think that it could break my system, because I used Pacui a lot of times, and it is supposed to be user friendly application for beginner but I was mistaken.
It's partially my fault but I learned my lesson, and I will never use Pacui ever again, and I may never use Manjaro either because it's different with each update, and it's a little bit frustrating
You owe me some screen wipes
I posted a while back how to recover the /etc files mentioned if they get trashed, there are backups in /etc ending in a "-" (minus sign) that do not get hosed.
ls -la *-
-rw-r--r-- 1 root root 1053 May 28 21:26 group-
-rw------- 1 root root 892 May 28 21:26 gshadow-
-rw-r--r-- 1 root root 1824 May 28 21:26 passwd-
-rw------- 1 root root 1025 May 28 21:26 shadow-
Just copy them back!
you were indeed mistaken.
the second and third sentence of the first post in this topic / the github page:
thanks for your suggestion!
i will add it to pacui's help page.
i have just released version 1.10.3. changelog is available here: https://github.com/excalibur1234/pacui/releases/tag/1.10.3
PacUI is now able to read more alternate Pacman paths from its configuration file. Reading the Pacman configuration file should be reliable, too.
PacUI is now fully compatible with Pacman 5.1
Now pacman 5.1 recommends ? to use pacman-conf
command and not grep pacman.conf
in annonce :
implement pacman-conf, a new tool to safely parse pacman.conf, and use it in internal scripts
i have read this announcement, too. i was excited and immediately tried it.
unfortunately, i was not able to query pacman.conf (using pacman-conf) for anything else than repository names.
"pacman-conf -h" only mentions repositories. no word or example how to query file or directory paths....
i have added aurman support with the latest commit.
please report any problems you find.
notice that "aurman -Si <package_name>" does not work yet, which means there is no package information available!
aurman is now the AUR helper with the highest priority in pacui.
AUR helper priority in pacui is: Aurman/Trizen/Yay/Pikaur/Pakku/Yaourt/Pacaur
if you have multiple AUR helpers installed, you can manually choose your favorite by setting a variable within pacui as described here: https://github.com/excalibur1234/pacui#multiple-installed-aur-helpers
why not use an environment variable instead of propose to edit the file?
AUR_Helper="yaourt" pacui
or export in .bashrc