Não é possível usar métodos tradicionais, mas você pode abusar do apt-get removendo temporariamente seus arquivos de bloqueio, a abordagem envolveria:
- Desativar temporariamente os bloqueios do apt / dpkg
- Atualizar / Instalar / Remover software
- Mesclar alterações no banco de dados do dpkg
- Ativar os bloqueios do apt / dpkg
- Lucro
1. Desativar temporariamente os bloqueios do apt / dpkg
Mova temporariamente para outro local os seguintes arquivos:
- / var / lib / dpkg / lock
- / var / lib / dpkg / updates /
- / var / cache / apt / archives / lock
2. Atualizar / Instalar / Remover software
Execute o apt-get para instalar / remover software, Reconheça que o apt-get / dpkg escreve seu estado para:
- / var / lib / dpkg / status
firefox, htop, curl
, e suponhamos que seu pacote foo
remova curl
, portanto, na instalação do seu pacote, você deve ter firefox, htop, foo
, já que o dpkg atualiza seu estado uma vez por instância, seu estado aninhado será sobreposto pelo processo pai, deixando o seguinte status firefox, htop, curl, foo
Portanto, você não terá os arquivos curl ao redor, mas para o dpkg o pacote ainda será instalado, isso também acontecerá com o novo software e dependências.
Vamos supor que ofoo
packages instale apache2
, que depende em apache2-data
, você os esperaria no banco de dados do dpkg como: firefox, htop, curl, foo, apache2, apache2-data
, mas você terá firefox, htop, curl, foo
, a saída aninhada foi substituída por o processo pai que estava ciente apenas da instalação de foo
3. Mesclar alterações no banco de dados do dpkg
Para evitar essa confusão, você precisará cuidar das alterações do dpkg manualmente, já que o arquivo é substituído por outras instâncias do apt-get / dpkg que você precisaria para salvar as alterações em um local diferente. e aplicá-las ao arquivo original somente depois que a instância principal do apt-get / dpkg estiver pronta, já que seu script terminará antes que isso aconteça, você precisará deixar uma entrada do cronjob ou uma mão fez daemon.
4. Ativar os bloqueios do apt / dpkg
5. Lucro
Como o processo acima pode ser de alguma forma problemático, estou deixando uma implementação ingênua, não deixe de entendê-lo antes de usá-lo e esperar casos de canto.
package=my-pkg
_dpkg_suspend_process() {
#unlock standard files
busybox mv /var/lib/dpkg/lock /var/lib/dpkg/lock.suspended
busybox rm -rf /var/lib/dpkg/updates.suspended/
busybox mv /var/lib/dpkg/updates/ /var/lib/dpkg/updates.suspended
busybox mkdir /var/lib/dpkg/updates/
busybox mv /var/cache/apt/archives/lock /var/cache/apt/archives/lock.suspended
#debconf missing file descriptors workaround
busybox cp /usr/share/debconf/confmodule /usr/share/debconf/confmodule.bk
busybox cp /usr/share/minos/debconf/confmodule /usr/share/debconf/confmodule
#while apt is being executed it modifies the status file which brings conflicts
#to new packages if they're installed/removed in abused apt instances, therefore
#the status-old file (which represent the original state in which the first
#apt instance was launched) is used to create temporal diffs which will be merged
#at the end
busybox cp /var/lib/dpkg/status /var/lib/dpkg/status.suspended
busybox cp /var/lib/dpkg/status-old /var/lib/dpkg/status-orig
busybox cp /var/lib/dpkg/status-orig /var/lib/dpkg/status
}
_dpkg_continue_process() {
#relock standard files
busybox rm -rf /var/lib/dpkg/updates
busybox mv /var/lib/dpkg/lock.suspended /var/lib/dpkg/lock
busybox mv /var/lib/dpkg/updates.suspended /var/lib/dpkg/updates
busybox mv /var/cache/apt/archives/lock.suspended /var/cache/apt/archives/lock
busybox mv /var/lib/dpkg/status.suspended /var/lib/dpkg/status
#debconf missing file descriptors workaround
busybox mv /usr/share/debconf/confmodule.bk /usr/share/debconf/confmodule
#keep status-old file to survive multiple abused apt instances
busybox mv /var/lib/dpkg/status-orig /var/lib/dpkg/status-old
}
_dpkg_sync_status_db() {
_dpkg_sync_status_db_script="/var/lib/dpkg/dpkg-sync-status-db"
_dpkg_sync_status_db_script_generator() {
printf "%s\n" "#!/bin/sh"
printf "%s\n" "#autogenerated by ${package}: $(date +%d-%m-%Y:%H:%M)"
printf "\n"
printf "%s\n" '##close stdout'
printf "%s\n" '#exec 1<&-'
printf "%s\n" '##close stderr'
printf "%s\n" '#exec 2<&-'
printf "%s\n" '##open stdout as $log_file file for read and write.'
printf "%s\n" "#exec 1<> /tmp/${package}.\${$}.debug"
printf "%s\n" '##redirect stderr to stdout'
printf "%s\n" '#exec 2>&1'
printf "%s\n" '#set -x #enable trace mode'
printf "\n"
printf "%s\n" "while fuser /var/lib/dpkg/lock >/dev/null 2>&1; do sleep 1; done"
printf "\n"
printf "%s\n" 'pkgs__add="$(cat /var/lib/apt/apt-add-queue)"'
printf "%s\n" 'if [ -n "${pkgs__add}" ]; then'
printf "%s\n" ' for pkg in $pkgs__add; do'
printf "%s\n" ' if ! busybox grep "^Package: ${pkg}$" /var/lib/dpkg/status >/dev/null 2>&1; then'
printf "%s\n" ' busybox sed -n "/Package: ${pkg}$/,/^$/p" \'
printf "%s\n" " /var/lib/dpkg/status-append-queue >> /var/lib/dpkg/status"
printf "%s\n" " fi"
printf "%s\n" " done"
printf "%s\n" "fi"
printf "\n"
printf "%s\n" 'pkgs__rm="$(cat /var/lib/apt/apt-rm-queue)"'
printf "%s\n" 'if [ -n "${pkgs__rm}" ]; then'
printf "%s\n" ' for pkg in $pkgs__rm; do'
printf "%s\n" ' busybox sed -i "/Package: ${pkg}$/,/^$/d" /var/lib/dpkg/status'
printf "%s\n" " done"
printf "%s\n" "fi"
printf "\n"
printf "%s\n" "mv /var/lib/apt/apt-add-queue /var/lib/apt/apt-add-queue.bk"
printf "%s\n" "mv /var/lib/apt/apt-rm-queue /var/lib/apt/apt-rm-queue.bk"
printf "%s\n" "mv /var/lib/dpkg/status-append-queue /var/lib/dpkg/status-append-queue.bk"
printf "\n"
printf "%s\n" "rm -rf /var/lib/apt/apt-add-queue /var/lib/apt/apt-rm-queue"
printf "%s\n" "rm -rf ${_dpkg_sync_status_db_script}"
}
_dpkg_sync_status_db_script_generator > "${_dpkg_sync_status_db_script}"
chmod +x "${_dpkg_sync_status_db_script}"
_daemonize /bin/sh -c "${_dpkg_sync_status_db_script}"
}
_daemonize() {
#http://blog.n01se.net/blog-n01se-net-p-145.html
[ -z "${1}" ] && return 1
( #1. fork, to guarantee the child is not a process
#group leader, necessary for setsid) and have the
#parent exit (to allow control to return to the shell)
#2. redirect stdin/stdout/stderr before running child
[ -t 0 ] && exec </dev/null
[ -t 1 ] && exec >/dev/null
[ -t 2 ] && exec 2>/dev/null
if ! command -v "setsid" >/dev/null 2>&1; then
#2.1 guard against HUP and INT (in child)
trap '' 1 2
fi
#3. ensure cwd isn't a mounted fs so it does't block
#umo unt invocations
cd /
#4. umask (leave this to caller)
#umask 0
#5. close unneeded fds
#XCU 2.7 Redirection says: open files are represented by
#decimal numbers starting with zero. The largest possible
#value is implementation-defined; however, all
#implementations shall support at least 0 to 9, inclusive,
#for use by the application.
i=3; while [ "${i}" -le "9" ]; do
eval "exec ${i}>&-"
i="$(($i + 1))"
done
#6. create new session, so the child has no
#controlling terminal, this prevents the child from
#accesing a terminal (using /dev/tty) and getting
#signals from the controlling terminal (e.g. HUP, INT)
if command -v "setsid" >/dev/null 2>&1; then
exec setsid "$@"
elif command -v "nohup" >/dev/null 2>&1; then
exec nohup "$@" >/dev/null 2>&1
else
if [ ! -f "${1}" ]; then
"$@"
else
exec "$@"
fi
fi
) &
#2.2 guard against HUP (in parent)
if ! command -v "setsid" >/dev/null 2>&1 \ &&
! command -v "nohup" >/dev/null 2>&1; then
disown -h "${!}"
fi
}
_apt_add_queue() {
for pkg in "${@}"; do
if busybox grep "${pkg}" /var/lib/apt/apt-rm-queue >/dev/null 2>&1; then
busybox sed -i "/^${pkg}$/d" /var/lib/apt/apt-rm-queue
else
if ! busybox grep "^Package: ${pkg}$" /var/lib/dpkg/status >/dev/null 2>&1; then
printf "%s\n" "${pkg}" >> /var/lib/apt/apt-add-queue
fi
fi
done; unset pkg
}
_apt_rm_queue() {
for pkg in "${@}"; do
if busybox grep "${pkg}" /var/lib/apt/apt-add-queue >/dev/null 2>&1; then
busybox sed -i "/^${pkg}$/d" /var/lib/apt/apt-add-queue
else
if busybox grep "^Package: ${pkg}$" /var/lib/dpkg/status >/dev/null 2>&1; then
printf "%s\n" "${pkg}" >> /var/lib/apt/apt-rm-queue
fi
fi
done; unset pkg
}
_apt_install() {
[ -z "${1}" ] && return
_apt_add_queue $(printf "%s\n" "${@}" | busybox sed "s:${package}::g")
}
_apt_purge() {
[ -z "${1}" ] && return
_apt_rm_queue $(printf "%s\n" "${@}" | busybox sed "s:${package}::g")
}
_apt_run() {
[ ! -f /var/lib/apt/apt-add-queue ] && [ ! -f /var/lib/apt/apt-rm-queue ] && return
pkgs__add="$(cat /var/lib/apt/apt-add-queue 2>/dev/null)"
if [ -n "${pkgs__add}" ]; then
_dpkg_suspend_process
busybox awk '/^Package: /{print $2}' /var/lib/dpkg/status | \
busybox sort > /var/lib/dpkg/status-pkgs.orig
_apt_run__output="$(DEBIAN_FRONTEND=noninteractive apt-get install \
--no-install-recommends -y -o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" --force-yes ${pkgs__add} 2>&1)" || \
printf "%s\n" "${_apt_run__output}" >&2
busybox awk '/^Package: /{print $2}' /var/lib/dpkg/status | \
busybox sort > /var/lib/dpkg/status-pkgs.current
_dpkg__added_pkgs="$(busybox diff -Naur /var/lib/dpkg/status-pkgs.orig \
/var/lib/dpkg/status-pkgs.current | busybox awk '/^\+[a-zA-Z]/{gsub("^+","");print;}')"
busybox rm -rf /var/lib/dpkg/status-pkgs*
#add dependencies
if [ -n "${_dpkg__added_pkgs}" ]; then
printf "%s\n" "${_dpkg__added_pkgs}" >> /var/lib/apt/apt-add-queue
printf "%s\n" "$(busybox sort /var/lib/apt/apt-add-queue | busybox uniq)" \
> /var/lib/apt/apt-add-queue
fi
#extract dpkg status output to append it at the end
for pkg in $_dpkg__added_pkgs; do
busybox sed -n '/Package: '"${pkg}"'$/,/^$/p' /var/lib/dpkg/status \
>> /var/lib/dpkg/status-append-queue
done
_dpkg_continue_process
fi
pkgs__rm="$(cat /var/lib/apt/apt-rm-queue 2>/dev/null)"
if [ -n "${pkgs__rm}" ]; then
_dpkg_suspend_process
busybox awk '/^Package: /{print $2}' /var/lib/dpkg/status | \
busybox sort > /var/lib/dpkg/status-pkgs.orig
_apt_run__output="$(DEBIAN_FRONTEND=noninteractive apt-get purge \
-y ${pkgs__rm} 2>&1)" || printf "%s\n" "${_apt_run__output}" >&2
busybox awk '/^Package: /{print $2}' /var/lib/dpkg/status | \
busybox sort > /var/lib/dpkg/status-pkgs.current
_dpkg__removed_pkgs="$(busybox diff -Naur /var/lib/dpkg/status-pkgs.orig \
/var/lib/dpkg/status-pkgs.current | busybox awk '/^-[a-zA-Z]/{gsub("^-","");print;}')"
busybox rm -rf /var/lib/dpkg/status-pkgs*
#remove dependencies
if [ -n "${_dpkg__removed_pkgs}" ]; then
printf "%s\n" "${_dpkg__removed_pkgs}" >> /var/lib/apt/apt-rm-queue
printf "%s\n" "$(busybox sort /var/lib/apt/apt-rm-queue | busybox uniq)" \
> /var/lib/apt/apt-rm-queue
fi
_dpkg_continue_process
fi
_dpkg_sync_status_db
}
_apt_install foo bar
_apt_purge ugly packages
_apt_run