segfault/encfsd/destructor.sh

137 lines
3.4 KiB
Bash
Raw Normal View History

2022-10-11 05:01:14 +00:00
#! /bin/bash
source /sf/bin/funcs.sh
# [LID] <1=encfs> <1=Container>
# Either parameter can be "" to not stop encfs or lg-container
stop_lg()
{
local is_encfs
local is_container
local lid
lid="$1"
is_encfs="$2"
is_container="$3"
2022-10-11 12:51:11 +00:00
LOG "$lid" "Stopping"
2022-10-11 05:01:14 +00:00
redis-cli -h 172.20.2.254 RPUSH portd:cmd "remport ${lid}" >/dev/null
# Tear down container
[[ ! -z $is_container ]] && docker stop "lg-$lid" &>/dev/nuill
2022-10-11 12:51:11 +00:00
[[ ! -z $is_encfs ]] && { pkill -SIGTERM -f "^\[encfs-${lid}\]" || ERR "[${lid}] pkill"; }
2022-10-11 05:01:14 +00:00
}
2022-10-18 17:57:35 +00:00
# Return 0 if we shall not check this container further
# - It's recent
# - It no longer exists.
2022-10-11 05:01:14 +00:00
is_recent()
{
local pid
local ts
pid="$1"
2022-10-11 12:51:11 +00:00
[[ -z "${pid}" ]] && { WARN "PID='${pid}' is empty"; return 0; }
2022-10-18 17:57:35 +00:00
ts=$(stat -c %Y "/proc/${pid}" 2>/dev/null) || return 0
# Can happen that container quit just now. Ignore if failed.
2022-10-11 05:01:14 +00:00
[[ -z $ts ]] && return 0
# PID is younger than 20 seconds...
[[ $((NOW - ts)) -lt 20 ]] && return 0
return 255
}
# [lg-$LID]
# Check if lg- is running but EncFS died.
# Check if user logged out.
check_container()
{
local c
local lid
local pid
c="$1"
lid="${c#lg-}"
[[ ${#lid} -ne 10 ]] && return
# Check if EncFS still exists.
2022-10-11 12:51:11 +00:00
pid=$(pgrep -f "^\[encfs-${lid}\]" -a 2>/dev/null) || {
ERR "[${CDM}${lid}${CN}] EncFS died..."
2022-10-11 05:01:14 +00:00
stop_lg "$lid" "" "lg"
return
}
# Skip if this container only started recently.
is_recent "${pid%% *}" && return
# Check how many PIDS are running inside container:
2022-10-18 17:57:35 +00:00
pids=($(docker top "$c" -eo pid 2>/dev/null)) || { DEBUGF "docker top '$c' failed"; return; }
2022-10-11 12:51:11 +00:00
# DEBUGF "[${CDM}${lid}${CN}] pids(${#pids[@]}) '${pids[*]}'"
2022-10-11 05:01:14 +00:00
# 1. PS-Header (UID PID PPID C STIME TTY TIME)
# 2. docker-init
# 3. sleep infinity
# 4. zsh user shell
[[ "${#pids[@]}" -ge 4 ]] && return
stop_lg "${lid}" "encfs" "lg"
}
# Check if EncFS is running but lg- died.
check_stale_mounts()
{
local encs
local IFS
IFS=$'\n'
encs=($(pgrep -f '^\[encfs-.*raw/user/user-' -a))
i=0
n=${#encs[@]}
while [[ $i -lt $n ]]; do
# 16249 [encfs-MzAZGViYTE] --standard --public -o nonempty -S /encfs/raw/user/user-MzAZGViYTE /encfs/sec/user-MzAZGViYTE -- -o noatime
lid="${encs[$i]}"
((i++))
# There is a race condition here:
# 1. encfs starts
# 2. Container is not yet started
# 3. encfs is killed here.
# Give EncFS at least 20 seconds to live and time for lg-container to start.
is_recent "${lid%% *}" && continue
lid="${lid%%\]*}"
lid="${lid#*\[encfs-}"
[[ ${#lid} -ne 10 ]] && continue
docker container inspect "lg-${lid}" -f '{{.State.Status}}' &>/dev/null && continue
2022-10-11 12:51:11 +00:00
ERR "[${CDM}${lid}${CN}] Unmounting stale EncFS (lg-${lid} died)."
2022-10-11 05:01:14 +00:00
stop_lg "${lid}" "encfs" ""
done
}
[[ ! -S /var/run/docker.sock ]] && ERREXIT 255 "Not found: /var/run/docker.sock"
export REDISCLI_AUTH="${SF_REDIS_AUTH}"
while :; do
2022-10-11 12:51:11 +00:00
sleep 5 # Check every 10 seconds. wait 5 here and 5 below.
2022-10-11 05:01:14 +00:00
NOW=$(date +%s)
# Every 30 seconds check all running lg-containers if they need killing.
# docker ps -f "name=^lg" --format "{{.ID}} {{.Names}}"
containers=($(docker ps -f "name=^lg-" --format "{{.Names}}"))
[[ -z $containers ]] && continue
i=0
n=${#containers[@]}
while [[ $i -lt $n ]]; do
check_container "${containers[$i]}"
((i++))
done
2022-10-11 12:51:11 +00:00
# We must give EncFS time to die by SIGTERM or otherwise check_stale_mounts
# still sees the encfs and tries to kill it again (which would yield an ugly
# warning).
sleep 5
2022-10-11 05:01:14 +00:00
check_stale_mounts
done