Add per-container resource limits and optimize TUI performance
Features: - Per-container CPU and memory limits via Settings menu - Resource limit prompts when adding containers in Container Management - Smart defaults based on system specs (cores, RAM) - Limits persist in settings.conf and apply on container create/recreate - Settings table shows CPU/Memory columns alongside max-clients/bandwidth - Resource limit changes detected on restart/start, triggering container recreation Performance optimizations: - Parallelize all docker logs calls across containers (background jobs) - Run docker stats, system stats, and net speed concurrently - Batch docker inspect calls instead of per-container - Parallel container stop/remove with -t 3 timeout (was 10s default) - All screens optimized: Status, Container Management, Advanced Stats, Live Peers Bug fixes: - Normalize grep pattern to [STATS] across all screens - Clean temp dirs before reuse to prevent stale data reads - Check exit status on container remove operations Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
601
conduit.sh
601
conduit.sh
@@ -646,6 +646,12 @@ run_conduit() {
|
|||||||
docker run --rm -v "${vname}:/home/conduit/data" alpine \
|
docker run --rm -v "${vname}:/home/conduit/data" alpine \
|
||||||
sh -c "chown -R 1000:1000 /home/conduit/data" 2>/dev/null || true
|
sh -c "chown -R 1000:1000 /home/conduit/data" 2>/dev/null || true
|
||||||
|
|
||||||
|
local resource_args=""
|
||||||
|
local cpus=$(get_container_cpus $i)
|
||||||
|
local mem=$(get_container_memory $i)
|
||||||
|
[ -n "$cpus" ] && resource_args+="--cpus $cpus "
|
||||||
|
[ -n "$mem" ] && resource_args+="--memory $mem "
|
||||||
|
# shellcheck disable=SC2086
|
||||||
docker run -d \
|
docker run -d \
|
||||||
--name "$cname" \
|
--name "$cname" \
|
||||||
--restart unless-stopped \
|
--restart unless-stopped \
|
||||||
@@ -653,6 +659,7 @@ run_conduit() {
|
|||||||
--log-opt max-file=3 \
|
--log-opt max-file=3 \
|
||||||
-v "${vname}:/home/conduit/data" \
|
-v "${vname}:/home/conduit/data" \
|
||||||
--network host \
|
--network host \
|
||||||
|
$resource_args \
|
||||||
"$CONDUIT_IMAGE" \
|
"$CONDUIT_IMAGE" \
|
||||||
start --max-clients "$MAX_CLIENTS" --bandwidth "$BANDWIDTH" --stats-file
|
start --max-clients "$MAX_CLIENTS" --bandwidth "$BANDWIDTH" --stats-file
|
||||||
|
|
||||||
@@ -954,16 +961,36 @@ get_container_bandwidth() {
|
|||||||
echo "${val:-$BANDWIDTH}"
|
echo "${val:-$BANDWIDTH}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_container_cpus() {
|
||||||
|
local idx=${1:-1}
|
||||||
|
local var="CPUS_${idx}"
|
||||||
|
local val="${!var}"
|
||||||
|
echo "${val:-${DOCKER_CPUS:-}}"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_container_memory() {
|
||||||
|
local idx=${1:-1}
|
||||||
|
local var="MEMORY_${idx}"
|
||||||
|
local val="${!var}"
|
||||||
|
echo "${val:-${DOCKER_MEMORY:-}}"
|
||||||
|
}
|
||||||
|
|
||||||
run_conduit_container() {
|
run_conduit_container() {
|
||||||
local idx=${1:-1}
|
local idx=${1:-1}
|
||||||
local name=$(get_container_name $idx)
|
local name=$(get_container_name $idx)
|
||||||
local vol=$(get_volume_name $idx)
|
local vol=$(get_volume_name $idx)
|
||||||
local mc=$(get_container_max_clients $idx)
|
local mc=$(get_container_max_clients $idx)
|
||||||
local bw=$(get_container_bandwidth $idx)
|
local bw=$(get_container_bandwidth $idx)
|
||||||
|
local cpus=$(get_container_cpus $idx)
|
||||||
|
local mem=$(get_container_memory $idx)
|
||||||
# Remove any existing container with the same name to avoid conflicts
|
# Remove any existing container with the same name to avoid conflicts
|
||||||
if docker ps -a 2>/dev/null | grep -q "[[:space:]]${name}$"; then
|
if docker ps -a 2>/dev/null | grep -q "[[:space:]]${name}$"; then
|
||||||
docker rm -f "$name" 2>/dev/null || true
|
docker rm -f "$name" 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
local resource_args=""
|
||||||
|
[ -n "$cpus" ] && resource_args+="--cpus $cpus "
|
||||||
|
[ -n "$mem" ] && resource_args+="--memory $mem "
|
||||||
|
# shellcheck disable=SC2086
|
||||||
docker run -d \
|
docker run -d \
|
||||||
--name "$name" \
|
--name "$name" \
|
||||||
--restart unless-stopped \
|
--restart unless-stopped \
|
||||||
@@ -971,6 +998,7 @@ run_conduit_container() {
|
|||||||
--log-opt max-file=3 \
|
--log-opt max-file=3 \
|
||||||
-v "${vol}:/home/conduit/data" \
|
-v "${vol}:/home/conduit/data" \
|
||||||
--network host \
|
--network host \
|
||||||
|
$resource_args \
|
||||||
"$CONDUIT_IMAGE" \
|
"$CONDUIT_IMAGE" \
|
||||||
start --max-clients "$mc" --bandwidth "$bw" --stats-file
|
start --max-clients "$mc" --bandwidth "$bw" --stats-file
|
||||||
}
|
}
|
||||||
@@ -1940,16 +1968,23 @@ show_advanced_stats() {
|
|||||||
|
|
||||||
echo -e "${CYAN}║${NC} ${GREEN}CONTAINER${NC} ${DIM}|${NC} ${YELLOW}NETWORK${NC} ${DIM}|${NC} ${MAGENTA}TRACKER${NC}\033[K"
|
echo -e "${CYAN}║${NC} ${GREEN}CONTAINER${NC} ${DIM}|${NC} ${YELLOW}NETWORK${NC} ${DIM}|${NC} ${MAGENTA}TRACKER${NC}\033[K"
|
||||||
|
|
||||||
# Single docker stats call for all running containers
|
# Fetch docker stats and all container logs in parallel
|
||||||
local adv_running_names=""
|
local adv_running_names=""
|
||||||
|
local _adv_tmpdir="/tmp/.conduit_adv_$$"
|
||||||
|
rm -rf "$_adv_tmpdir"; mkdir -p "$_adv_tmpdir"
|
||||||
for ci in $(seq 1 $CONTAINER_COUNT); do
|
for ci in $(seq 1 $CONTAINER_COUNT); do
|
||||||
local cname=$(get_container_name $ci)
|
local cname=$(get_container_name $ci)
|
||||||
echo "$docker_ps_cache" | grep -q "^${cname}$" && adv_running_names+=" $cname"
|
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
|
||||||
|
adv_running_names+=" $cname"
|
||||||
|
( docker logs --tail 30 "$cname" 2>&1 | grep "\[STATS\]" | tail -1 > "$_adv_tmpdir/logs_${ci}" ) &
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
local adv_all_stats=""
|
local adv_all_stats=""
|
||||||
if [ -n "$adv_running_names" ]; then
|
if [ -n "$adv_running_names" ]; then
|
||||||
adv_all_stats=$(docker stats --no-stream --format "{{.Name}}|{{.CPUPerc}}|{{.MemUsage}}" $adv_running_names 2>/dev/null)
|
( docker stats --no-stream --format "{{.Name}}|{{.CPUPerc}}|{{.MemUsage}}" $adv_running_names > "$_adv_tmpdir/stats" 2>/dev/null ) &
|
||||||
fi
|
fi
|
||||||
|
wait
|
||||||
|
[ -f "$_adv_tmpdir/stats" ] && adv_all_stats=$(cat "$_adv_tmpdir/stats")
|
||||||
|
|
||||||
for ci in $(seq 1 $CONTAINER_COUNT); do
|
for ci in $(seq 1 $CONTAINER_COUNT); do
|
||||||
local cname=$(get_container_name $ci)
|
local cname=$(get_container_name $ci)
|
||||||
@@ -1972,7 +2007,8 @@ show_advanced_stats() {
|
|||||||
fi
|
fi
|
||||||
[ -z "$first_mem_limit" ] && first_mem_limit=$(echo "$stats" | cut -d'|' -f3 | awk -F'/' '{print $2}' | xargs)
|
[ -z "$first_mem_limit" ] && first_mem_limit=$(echo "$stats" | cut -d'|' -f3 | awk -F'/' '{print $2}' | xargs)
|
||||||
|
|
||||||
local logs=$(docker logs --tail 50 "$cname" 2>&1 | grep "\[STATS\]" | tail -1)
|
local logs=""
|
||||||
|
[ -f "$_adv_tmpdir/logs_${ci}" ] && logs=$(cat "$_adv_tmpdir/logs_${ci}")
|
||||||
local conn=$(echo "$logs" | sed -n 's/.*Connected:[[:space:]]*\([0-9]*\).*/\1/p')
|
local conn=$(echo "$logs" | sed -n 's/.*Connected:[[:space:]]*\([0-9]*\).*/\1/p')
|
||||||
[[ "$conn" =~ ^[0-9]+$ ]] && total_conn=$((total_conn + conn))
|
[[ "$conn" =~ ^[0-9]+$ ]] && total_conn=$((total_conn + conn))
|
||||||
|
|
||||||
@@ -2005,6 +2041,7 @@ show_advanced_stats() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
rm -rf "$_adv_tmpdir"
|
||||||
|
|
||||||
if [ "$container_count" -gt 0 ]; then
|
if [ "$container_count" -gt 0 ]; then
|
||||||
local cpu_display="${total_cpu}%"
|
local cpu_display="${total_cpu}%"
|
||||||
@@ -2203,17 +2240,26 @@ show_peers() {
|
|||||||
done < "$persist_dir/cumulative_ips"
|
done < "$persist_dir/cumulative_ips"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get actual connected clients from docker logs
|
# Get actual connected clients from docker logs (parallel)
|
||||||
local total_clients=0
|
local total_clients=0
|
||||||
local docker_ps_cache=$(docker ps --format '{{.Names}}' 2>/dev/null)
|
local docker_ps_cache=$(docker ps --format '{{.Names}}' 2>/dev/null)
|
||||||
|
local _peer_tmpdir="/tmp/.conduit_peer_$$"
|
||||||
|
rm -rf "$_peer_tmpdir"; mkdir -p "$_peer_tmpdir"
|
||||||
for ci in $(seq 1 $CONTAINER_COUNT); do
|
for ci in $(seq 1 $CONTAINER_COUNT); do
|
||||||
local cname=$(get_container_name $ci)
|
local cname=$(get_container_name $ci)
|
||||||
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
|
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
|
||||||
local logs=$(docker logs --tail 50 "$cname" 2>&1 | grep "\[STATS\]" | tail -1)
|
( docker logs --tail 30 "$cname" 2>&1 | grep "\[STATS\]" | tail -1 > "$_peer_tmpdir/logs_${ci}" ) &
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
wait
|
||||||
|
for ci in $(seq 1 $CONTAINER_COUNT); do
|
||||||
|
if [ -f "$_peer_tmpdir/logs_${ci}" ]; then
|
||||||
|
local logs=$(cat "$_peer_tmpdir/logs_${ci}")
|
||||||
local conn=$(echo "$logs" | sed -n 's/.*Connected:[[:space:]]*\([0-9]*\).*/\1/p')
|
local conn=$(echo "$logs" | sed -n 's/.*Connected:[[:space:]]*\([0-9]*\).*/\1/p')
|
||||||
[[ "$conn" =~ ^[0-9]+$ ]] && total_clients=$((total_clients + conn))
|
[[ "$conn" =~ ^[0-9]+$ ]] && total_clients=$((total_clients + conn))
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
rm -rf "$_peer_tmpdir"
|
||||||
|
|
||||||
echo -e "${EL}"
|
echo -e "${EL}"
|
||||||
|
|
||||||
@@ -2369,6 +2415,9 @@ show_status() {
|
|||||||
local total_connected=0
|
local total_connected=0
|
||||||
local uptime=""
|
local uptime=""
|
||||||
|
|
||||||
|
# Fetch all container logs in parallel
|
||||||
|
local _st_tmpdir="/tmp/.conduit_st_$$"
|
||||||
|
rm -rf "$_st_tmpdir"; mkdir -p "$_st_tmpdir"
|
||||||
for i in $(seq 1 $CONTAINER_COUNT); do
|
for i in $(seq 1 $CONTAINER_COUNT); do
|
||||||
local cname=$(get_container_name $i)
|
local cname=$(get_container_name $i)
|
||||||
_c_running[$i]=false
|
_c_running[$i]=false
|
||||||
@@ -2380,9 +2429,15 @@ show_status() {
|
|||||||
if echo "$docker_ps_cache" | grep -q "[[:space:]]${cname}$"; then
|
if echo "$docker_ps_cache" | grep -q "[[:space:]]${cname}$"; then
|
||||||
_c_running[$i]=true
|
_c_running[$i]=true
|
||||||
running_count=$((running_count + 1))
|
running_count=$((running_count + 1))
|
||||||
local logs=$(docker logs --tail 50 "$cname" 2>&1 | grep "STATS" | tail -1)
|
( docker logs --tail 30 "$cname" 2>&1 | grep "\[STATS\]" | tail -1 > "$_st_tmpdir/logs_${i}" ) &
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
wait
|
||||||
|
|
||||||
|
for i in $(seq 1 $CONTAINER_COUNT); do
|
||||||
|
if [ "${_c_running[$i]}" = true ] && [ -f "$_st_tmpdir/logs_${i}" ]; then
|
||||||
|
local logs=$(cat "$_st_tmpdir/logs_${i}")
|
||||||
if [ -n "$logs" ]; then
|
if [ -n "$logs" ]; then
|
||||||
# Single awk to extract all 5 fields, pipe-delimited
|
|
||||||
IFS='|' read -r c_connecting c_connected c_up_val c_down_val c_uptime_val <<< $(echo "$logs" | awk '{
|
IFS='|' read -r c_connecting c_connected c_up_val c_down_val c_uptime_val <<< $(echo "$logs" | awk '{
|
||||||
cing=0; conn=0; up=""; down=""; ut=""
|
cing=0; conn=0; up=""; down=""; ut=""
|
||||||
for(j=1;j<=NF;j++){
|
for(j=1;j<=NF;j++){
|
||||||
@@ -2406,6 +2461,7 @@ show_status() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
rm -rf "$_st_tmpdir"
|
||||||
local connecting=$total_connecting
|
local connecting=$total_connecting
|
||||||
local connected=$total_connected
|
local connected=$total_connected
|
||||||
# Export for parent function to reuse (avoids duplicate docker logs calls)
|
# Export for parent function to reuse (avoids duplicate docker logs calls)
|
||||||
@@ -2461,8 +2517,18 @@ show_status() {
|
|||||||
|
|
||||||
if [ "$running_count" -gt 0 ]; then
|
if [ "$running_count" -gt 0 ]; then
|
||||||
|
|
||||||
# Get Resource Stats
|
# Run all 3 resource stat calls in parallel
|
||||||
local stats=$(get_container_stats)
|
local _rs_tmpdir="/tmp/.conduit_rs_$$"
|
||||||
|
rm -rf "$_rs_tmpdir"; mkdir -p "$_rs_tmpdir"
|
||||||
|
( get_container_stats > "$_rs_tmpdir/cstats" ) &
|
||||||
|
( get_system_stats > "$_rs_tmpdir/sys" ) &
|
||||||
|
( get_net_speed > "$_rs_tmpdir/net" ) &
|
||||||
|
wait
|
||||||
|
|
||||||
|
local stats=$(cat "$_rs_tmpdir/cstats" 2>/dev/null)
|
||||||
|
local sys_stats=$(cat "$_rs_tmpdir/sys" 2>/dev/null)
|
||||||
|
local net_speed=$(cat "$_rs_tmpdir/net" 2>/dev/null)
|
||||||
|
rm -rf "$_rs_tmpdir"
|
||||||
|
|
||||||
# Normalize App CPU (Docker % / Cores)
|
# Normalize App CPU (Docker % / Cores)
|
||||||
local raw_app_cpu=$(echo "$stats" | awk '{print $1}' | tr -d '%')
|
local raw_app_cpu=$(echo "$stats" | awk '{print $1}' | tr -d '%')
|
||||||
@@ -2471,7 +2537,6 @@ show_status() {
|
|||||||
local app_cpu_display=""
|
local app_cpu_display=""
|
||||||
|
|
||||||
if [[ "$raw_app_cpu" =~ ^[0-9.]+$ ]]; then
|
if [[ "$raw_app_cpu" =~ ^[0-9.]+$ ]]; then
|
||||||
# Use awk for floating point math
|
|
||||||
app_cpu=$(awk -v cpu="$raw_app_cpu" -v cores="$num_cores" 'BEGIN {printf "%.2f%%", cpu / cores}')
|
app_cpu=$(awk -v cpu="$raw_app_cpu" -v cores="$num_cores" 'BEGIN {printf "%.2f%%", cpu / cores}')
|
||||||
if [ "$num_cores" -gt 1 ]; then
|
if [ "$num_cores" -gt 1 ]; then
|
||||||
app_cpu_display="${app_cpu} (${raw_app_cpu}% vCPU)"
|
app_cpu_display="${app_cpu} (${raw_app_cpu}% vCPU)"
|
||||||
@@ -2486,14 +2551,11 @@ show_status() {
|
|||||||
# Keep full "Used / Limit" string for App RAM
|
# Keep full "Used / Limit" string for App RAM
|
||||||
local app_ram=$(echo "$stats" | awk '{print $2, $3, $4}')
|
local app_ram=$(echo "$stats" | awk '{print $2, $3, $4}')
|
||||||
|
|
||||||
local sys_stats=$(get_system_stats)
|
|
||||||
local sys_cpu=$(echo "$sys_stats" | awk '{print $1}')
|
local sys_cpu=$(echo "$sys_stats" | awk '{print $1}')
|
||||||
local sys_ram_used=$(echo "$sys_stats" | awk '{print $2}')
|
local sys_ram_used=$(echo "$sys_stats" | awk '{print $2}')
|
||||||
local sys_ram_total=$(echo "$sys_stats" | awk '{print $3}')
|
local sys_ram_total=$(echo "$sys_stats" | awk '{print $3}')
|
||||||
local sys_ram_pct=$(echo "$sys_stats" | awk '{print $4}')
|
local sys_ram_pct=$(echo "$sys_stats" | awk '{print $4}')
|
||||||
|
|
||||||
# New Metric: Network Speed (System Wide)
|
|
||||||
local net_speed=$(get_net_speed)
|
|
||||||
local rx_mbps=$(echo "$net_speed" | awk '{print $1}')
|
local rx_mbps=$(echo "$net_speed" | awk '{print $1}')
|
||||||
local tx_mbps=$(echo "$net_speed" | awk '{print $2}')
|
local tx_mbps=$(echo "$net_speed" | awk '{print $2}')
|
||||||
local net_display="↓ ${rx_mbps} Mbps ↑ ${tx_mbps} Mbps"
|
local net_display="↓ ${rx_mbps} Mbps ↑ ${tx_mbps} Mbps"
|
||||||
@@ -2714,6 +2776,8 @@ restart_conduit() {
|
|||||||
local vol=$(get_volume_name $i)
|
local vol=$(get_volume_name $i)
|
||||||
local want_mc=$(get_container_max_clients $i)
|
local want_mc=$(get_container_max_clients $i)
|
||||||
local want_bw=$(get_container_bandwidth $i)
|
local want_bw=$(get_container_bandwidth $i)
|
||||||
|
local want_cpus=$(get_container_cpus $i)
|
||||||
|
local want_mem=$(get_container_memory $i)
|
||||||
|
|
||||||
if docker ps 2>/dev/null | grep -q "[[:space:]]${name}$"; then
|
if docker ps 2>/dev/null | grep -q "[[:space:]]${name}$"; then
|
||||||
# Container is running — check if settings match
|
# Container is running — check if settings match
|
||||||
@@ -2724,6 +2788,19 @@ restart_conduit() {
|
|||||||
local cur_bw=$(echo "$cur_args" | sed -n 's/.*--bandwidth \([^ ]*\).*/\1/p' 2>/dev/null)
|
local cur_bw=$(echo "$cur_args" | sed -n 's/.*--bandwidth \([^ ]*\).*/\1/p' 2>/dev/null)
|
||||||
[ "$cur_mc" != "$want_mc" ] && needs_recreate=true
|
[ "$cur_mc" != "$want_mc" ] && needs_recreate=true
|
||||||
[ "$cur_bw" != "$want_bw" ] && needs_recreate=true
|
[ "$cur_bw" != "$want_bw" ] && needs_recreate=true
|
||||||
|
# Check resource limits
|
||||||
|
local cur_nano=$(docker inspect --format '{{.HostConfig.NanoCpus}}' "$name" 2>/dev/null || echo 0)
|
||||||
|
local cur_memb=$(docker inspect --format '{{.HostConfig.Memory}}' "$name" 2>/dev/null || echo 0)
|
||||||
|
local want_nano=0
|
||||||
|
[ -n "$want_cpus" ] && want_nano=$(awk -v c="$want_cpus" 'BEGIN{printf "%.0f", c*1000000000}')
|
||||||
|
local want_memb=0
|
||||||
|
if [ -n "$want_mem" ]; then
|
||||||
|
local mv=${want_mem%[mMgG]}
|
||||||
|
local mu=${want_mem: -1}
|
||||||
|
[[ "$mu" =~ [gG] ]] && want_memb=$((mv * 1073741824)) || want_memb=$((mv * 1048576))
|
||||||
|
fi
|
||||||
|
[ "${cur_nano:-0}" != "$want_nano" ] && needs_recreate=true
|
||||||
|
[ "${cur_memb:-0}" != "$want_memb" ] && needs_recreate=true
|
||||||
|
|
||||||
if [ "$needs_recreate" = true ]; then
|
if [ "$needs_recreate" = true ]; then
|
||||||
echo "Settings changed for ${name}, recreating..."
|
echo "Settings changed for ${name}, recreating..."
|
||||||
@@ -2746,7 +2823,17 @@ restart_conduit() {
|
|||||||
local cur_args=$(docker inspect --format '{{join .Args " "}}' "$name" 2>/dev/null)
|
local cur_args=$(docker inspect --format '{{join .Args " "}}' "$name" 2>/dev/null)
|
||||||
local cur_mc=$(echo "$cur_args" | sed -n 's/.*--max-clients \([^ ]*\).*/\1/p' 2>/dev/null)
|
local cur_mc=$(echo "$cur_args" | sed -n 's/.*--max-clients \([^ ]*\).*/\1/p' 2>/dev/null)
|
||||||
local cur_bw=$(echo "$cur_args" | sed -n 's/.*--bandwidth \([^ ]*\).*/\1/p' 2>/dev/null)
|
local cur_bw=$(echo "$cur_args" | sed -n 's/.*--bandwidth \([^ ]*\).*/\1/p' 2>/dev/null)
|
||||||
if [ "$cur_mc" != "$want_mc" ] || [ "$cur_bw" != "$want_bw" ]; then
|
local cur_nano=$(docker inspect --format '{{.HostConfig.NanoCpus}}' "$name" 2>/dev/null || echo 0)
|
||||||
|
local cur_memb=$(docker inspect --format '{{.HostConfig.Memory}}' "$name" 2>/dev/null || echo 0)
|
||||||
|
local want_nano=0
|
||||||
|
[ -n "$want_cpus" ] && want_nano=$(awk -v c="$want_cpus" 'BEGIN{printf "%.0f", c*1000000000}')
|
||||||
|
local want_memb=0
|
||||||
|
if [ -n "$want_mem" ]; then
|
||||||
|
local mv=${want_mem%[mMgG]}
|
||||||
|
local mu=${want_mem: -1}
|
||||||
|
[[ "$mu" =~ [gG] ]] && want_memb=$((mv * 1073741824)) || want_memb=$((mv * 1048576))
|
||||||
|
fi
|
||||||
|
if [ "$cur_mc" != "$want_mc" ] || [ "$cur_bw" != "$want_bw" ] || [ "${cur_nano:-0}" != "$want_nano" ] || [ "${cur_memb:-0}" != "$want_memb" ]; then
|
||||||
echo "Settings changed for ${name}, recreating..."
|
echo "Settings changed for ${name}, recreating..."
|
||||||
docker rm "$name" 2>/dev/null || true
|
docker rm "$name" 2>/dev/null || true
|
||||||
docker volume create "$vol" 2>/dev/null || true
|
docker volume create "$vol" 2>/dev/null || true
|
||||||
@@ -2800,15 +2887,19 @@ change_settings() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}═══ Current Settings ═══${NC}"
|
echo -e "${CYAN}═══ Current Settings ═══${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
printf " ${BOLD}%-12s %-12s %-12s${NC}\n" "Container" "Max Clients" "Bandwidth"
|
printf " ${BOLD}%-12s %-12s %-12s %-10s %-10s${NC}\n" "Container" "Max Clients" "Bandwidth" "CPU" "Memory"
|
||||||
echo -e " ${CYAN}────────────────────────────────────────${NC}"
|
echo -e " ${CYAN}──────────────────────────────────────────────────────────${NC}"
|
||||||
for i in $(seq 1 $CONTAINER_COUNT); do
|
for i in $(seq 1 $CONTAINER_COUNT); do
|
||||||
local cname=$(get_container_name $i)
|
local cname=$(get_container_name $i)
|
||||||
local mc=$(get_container_max_clients $i)
|
local mc=$(get_container_max_clients $i)
|
||||||
local bw=$(get_container_bandwidth $i)
|
local bw=$(get_container_bandwidth $i)
|
||||||
|
local cpus=$(get_container_cpus $i)
|
||||||
|
local mem=$(get_container_memory $i)
|
||||||
local bw_display="Unlimited"
|
local bw_display="Unlimited"
|
||||||
[ "$bw" != "-1" ] && bw_display="${bw} Mbps"
|
[ "$bw" != "-1" ] && bw_display="${bw} Mbps"
|
||||||
printf " %-12s %-12s %-12s\n" "$cname" "$mc" "$bw_display"
|
local cpu_d="${cpus:-—}"
|
||||||
|
local mem_d="${mem:-—}"
|
||||||
|
printf " %-12s %-12s %-12s %-10s %-10s\n" "$cname" "$mc" "$bw_display" "$cpu_d" "$mem_d"
|
||||||
done
|
done
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " Default: Max Clients=${GREEN}${MAX_CLIENTS}${NC} Bandwidth=${GREEN}$([ "$BANDWIDTH" = "-1" ] && echo "Unlimited" || echo "${BANDWIDTH} Mbps")${NC}"
|
echo -e " Default: Max Clients=${GREEN}${MAX_CLIENTS}${NC} Bandwidth=${GREEN}$([ "$BANDWIDTH" = "-1" ] && echo "Unlimited" || echo "${BANDWIDTH} Mbps")${NC}"
|
||||||
@@ -2924,6 +3015,188 @@ change_settings() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
change_resource_limits() {
|
||||||
|
local cpu_cores=$(nproc 2>/dev/null || grep -c ^processor /proc/cpuinfo 2>/dev/null || echo 1)
|
||||||
|
local ram_mb=$(awk '/MemTotal/{printf "%.0f", $2/1024}' /proc/meminfo 2>/dev/null || echo 512)
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}═══ RESOURCE LIMITS ═══${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e " Set CPU and memory limits per container."
|
||||||
|
echo -e " ${DIM}System: ${cpu_cores} CPU core(s), ${ram_mb} MB RAM${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Show current limits
|
||||||
|
printf " ${BOLD}%-12s %-12s %-12s${NC}\n" "Container" "CPU Limit" "Memory Limit"
|
||||||
|
echo -e " ${CYAN}────────────────────────────────────────${NC}"
|
||||||
|
for i in $(seq 1 $CONTAINER_COUNT); do
|
||||||
|
local cname=$(get_container_name $i)
|
||||||
|
local cpus=$(get_container_cpus $i)
|
||||||
|
local mem=$(get_container_memory $i)
|
||||||
|
local cpu_d="${cpus:-No limit}"
|
||||||
|
local mem_d="${mem:-No limit}"
|
||||||
|
[ -n "$cpus" ] && cpu_d="${cpus} cores"
|
||||||
|
printf " %-12s %-12s %-12s\n" "$cname" "$cpu_d" "$mem_d"
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Select target
|
||||||
|
echo -e " ${BOLD}Apply limits to:${NC}"
|
||||||
|
echo -e " ${GREEN}a${NC}) All containers"
|
||||||
|
for i in $(seq 1 $CONTAINER_COUNT); do
|
||||||
|
echo -e " ${GREEN}${i}${NC}) $(get_container_name $i)"
|
||||||
|
done
|
||||||
|
echo -e " ${GREEN}c${NC}) Clear all limits (remove restrictions)"
|
||||||
|
echo ""
|
||||||
|
read -p " Select (a/1-${CONTAINER_COUNT}/c): " target < /dev/tty || true
|
||||||
|
|
||||||
|
if [ "$target" = "c" ] || [ "$target" = "C" ]; then
|
||||||
|
DOCKER_CPUS=""
|
||||||
|
DOCKER_MEMORY=""
|
||||||
|
for i in $(seq 1 5); do
|
||||||
|
unset "CPUS_${i}" 2>/dev/null || true
|
||||||
|
unset "MEMORY_${i}" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
save_settings
|
||||||
|
echo -e " ${GREEN}✓ All resource limits cleared. Containers will use full system resources on next restart.${NC}"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local targets=()
|
||||||
|
if [ "$target" = "a" ] || [ "$target" = "A" ]; then
|
||||||
|
for i in $(seq 1 $CONTAINER_COUNT); do targets+=($i); done
|
||||||
|
elif [[ "$target" =~ ^[0-9]+$ ]] && [ "$target" -ge 1 ] && [ "$target" -le "$CONTAINER_COUNT" ]; then
|
||||||
|
targets+=($target)
|
||||||
|
else
|
||||||
|
echo -e " ${RED}Invalid selection.${NC}"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local rec_cpu=$(awk -v c="$cpu_cores" 'BEGIN{v=c/2; if(v<0.5) v=0.5; printf "%.1f", v}')
|
||||||
|
local rec_mem="256m"
|
||||||
|
[ "$ram_mb" -ge 2048 ] && rec_mem="512m"
|
||||||
|
[ "$ram_mb" -ge 4096 ] && rec_mem="1g"
|
||||||
|
|
||||||
|
# CPU limit prompt
|
||||||
|
echo ""
|
||||||
|
echo -e " ${CYAN}───────────────────────────────────────────────────────────────${NC}"
|
||||||
|
echo -e " ${BOLD}CPU Limit${NC}"
|
||||||
|
echo -e " Limits how much processor power this container can use."
|
||||||
|
echo -e " This prevents it from slowing down other services on your system."
|
||||||
|
echo -e ""
|
||||||
|
echo -e " ${DIM}Your system has ${GREEN}${cpu_cores}${NC}${DIM} core(s).${NC}"
|
||||||
|
echo -e " ${DIM} 0.5 = half a core 1.0 = one full core${NC}"
|
||||||
|
echo -e " ${DIM} 2.0 = two cores ${cpu_cores}.0 = all cores (no limit)${NC}"
|
||||||
|
echo -e ""
|
||||||
|
echo -e " Press Enter to keep current or use default."
|
||||||
|
echo -e " ${CYAN}───────────────────────────────────────────────────────────────${NC}"
|
||||||
|
local cur_cpus=$(get_container_cpus ${targets[0]})
|
||||||
|
local cpus_default="${cur_cpus:-${rec_cpu}}"
|
||||||
|
read -p " CPU limit [${cpus_default}]: " input_cpus < /dev/tty || true
|
||||||
|
|
||||||
|
# Validate CPU
|
||||||
|
local valid_cpus=""
|
||||||
|
if [ -z "$input_cpus" ]; then
|
||||||
|
# Enter pressed — keep current if set, otherwise no change
|
||||||
|
[ -n "$cur_cpus" ] && valid_cpus="$cur_cpus"
|
||||||
|
elif [[ "$input_cpus" =~ ^[0-9]+\.?[0-9]*$ ]]; then
|
||||||
|
local cpu_ok=$(awk -v val="$input_cpus" -v max="$cpu_cores" 'BEGIN { print (val > 0 && val <= max) ? "yes" : "no" }')
|
||||||
|
if [ "$cpu_ok" = "yes" ]; then
|
||||||
|
valid_cpus="$input_cpus"
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}Must be between 0.1 and ${cpu_cores}. Keeping current.${NC}"
|
||||||
|
[ -n "$cur_cpus" ] && valid_cpus="$cur_cpus"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}Invalid input. Keeping current.${NC}"
|
||||||
|
[ -n "$cur_cpus" ] && valid_cpus="$cur_cpus"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Memory limit prompt
|
||||||
|
echo ""
|
||||||
|
echo -e " ${CYAN}───────────────────────────────────────────────────────────────${NC}"
|
||||||
|
echo -e " ${BOLD}Memory Limit${NC}"
|
||||||
|
echo -e " Maximum RAM this container can use."
|
||||||
|
echo -e " Prevents it from consuming all memory and crashing other services."
|
||||||
|
echo -e ""
|
||||||
|
echo -e " ${DIM}Your system has ${GREEN}${ram_mb} MB${NC}${DIM} RAM.${NC}"
|
||||||
|
echo -e " ${DIM} 256m = 256 MB (good for low-end systems)${NC}"
|
||||||
|
echo -e " ${DIM} 512m = 512 MB (balanced)${NC}"
|
||||||
|
echo -e " ${DIM} 1g = 1 GB (high capacity)${NC}"
|
||||||
|
echo -e ""
|
||||||
|
echo -e " Press Enter to keep current or use default."
|
||||||
|
echo -e " ${CYAN}───────────────────────────────────────────────────────────────${NC}"
|
||||||
|
local cur_mem=$(get_container_memory ${targets[0]})
|
||||||
|
local mem_default="${cur_mem:-${rec_mem}}"
|
||||||
|
read -p " Memory limit [${mem_default}]: " input_mem < /dev/tty || true
|
||||||
|
|
||||||
|
# Validate memory
|
||||||
|
local valid_mem=""
|
||||||
|
if [ -z "$input_mem" ]; then
|
||||||
|
# Enter pressed — keep current if set, otherwise no change
|
||||||
|
[ -n "$cur_mem" ] && valid_mem="$cur_mem"
|
||||||
|
elif [[ "$input_mem" =~ ^[0-9]+[mMgG]$ ]]; then
|
||||||
|
local mem_val=${input_mem%[mMgG]}
|
||||||
|
local mem_unit=${input_mem: -1}
|
||||||
|
local mem_mb=$mem_val
|
||||||
|
[[ "$mem_unit" =~ [gG] ]] && mem_mb=$((mem_val * 1024))
|
||||||
|
if [ "$mem_mb" -ge 64 ] && [ "$mem_mb" -le "$ram_mb" ]; then
|
||||||
|
valid_mem="$input_mem"
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}Must be between 64m and ${ram_mb}m. Keeping current.${NC}"
|
||||||
|
[ -n "$cur_mem" ] && valid_mem="$cur_mem"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}Invalid format. Use a number followed by m or g (e.g. 256m, 1g). Keeping current.${NC}"
|
||||||
|
[ -n "$cur_mem" ] && valid_mem="$cur_mem"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Nothing changed
|
||||||
|
if [ -z "$valid_cpus" ] && [ -z "$valid_mem" ]; then
|
||||||
|
echo -e " ${DIM}No changes made.${NC}"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Apply
|
||||||
|
if [ "$target" = "a" ] || [ "$target" = "A" ]; then
|
||||||
|
[ -n "$valid_cpus" ] && DOCKER_CPUS="$valid_cpus"
|
||||||
|
[ -n "$valid_mem" ] && DOCKER_MEMORY="$valid_mem"
|
||||||
|
for i in $(seq 1 5); do
|
||||||
|
unset "CPUS_${i}" 2>/dev/null || true
|
||||||
|
unset "MEMORY_${i}" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
else
|
||||||
|
local idx=${targets[0]}
|
||||||
|
[ -n "$valid_cpus" ] && eval "CPUS_${idx}=${valid_cpus}"
|
||||||
|
[ -n "$valid_mem" ] && eval "MEMORY_${idx}=${valid_mem}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
save_settings
|
||||||
|
|
||||||
|
# Recreate affected containers
|
||||||
|
echo ""
|
||||||
|
echo " Recreating container(s) with new resource limits..."
|
||||||
|
for i in "${targets[@]}"; do
|
||||||
|
local name=$(get_container_name $i)
|
||||||
|
docker rm -f "$name" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
sleep 1
|
||||||
|
for i in "${targets[@]}"; do
|
||||||
|
local name=$(get_container_name $i)
|
||||||
|
fix_volume_permissions $i
|
||||||
|
run_conduit_container $i
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
local cpus=$(get_container_cpus $i)
|
||||||
|
local mem=$(get_container_memory $i)
|
||||||
|
local cpu_d="${cpus:-no limit}"
|
||||||
|
local mem_d="${mem:-no limit}"
|
||||||
|
[ -n "$cpus" ] && cpu_d="${cpus} cores"
|
||||||
|
echo -e " ${GREEN}✓ ${name}${NC} — CPU: ${cpu_d}, Memory: ${mem_d}"
|
||||||
|
else
|
||||||
|
echo -e " ${RED}✗ Failed to restart ${name}${NC}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
#═══════════════════════════════════════════════════════════════════════
|
#═══════════════════════════════════════════════════════════════════════
|
||||||
# show_logs() - Display color-coded Docker logs
|
# show_logs() - Display color-coded Docker logs
|
||||||
#═══════════════════════════════════════════════════════════════════════
|
#═══════════════════════════════════════════════════════════════════════
|
||||||
@@ -3115,18 +3388,27 @@ manage_containers() {
|
|||||||
# Per-container stats table
|
# Per-container stats table
|
||||||
local docker_ps_cache=$(docker ps --format '{{.Names}}' 2>/dev/null)
|
local docker_ps_cache=$(docker ps --format '{{.Names}}' 2>/dev/null)
|
||||||
|
|
||||||
# Single docker stats call for all running containers (instead of per-container)
|
# Collect all docker data in parallel using a temp dir
|
||||||
local all_dstats=""
|
local _mc_tmpdir="/tmp/.conduit_mc_$$"
|
||||||
|
rm -rf "$_mc_tmpdir"; mkdir -p "$_mc_tmpdir"
|
||||||
|
|
||||||
local running_names=""
|
local running_names=""
|
||||||
for ci in $(seq 1 $CONTAINER_COUNT); do
|
for ci in $(seq 1 $CONTAINER_COUNT); do
|
||||||
local cname=$(get_container_name $ci)
|
local cname=$(get_container_name $ci)
|
||||||
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
|
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
|
||||||
running_names+=" $cname"
|
running_names+=" $cname"
|
||||||
|
# Fetch logs in parallel background jobs
|
||||||
|
( docker logs --tail 30 "$cname" 2>&1 | grep "\[STATS\]" | tail -1 > "$_mc_tmpdir/logs_${ci}" ) &
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
# Fetch stats in parallel with logs
|
||||||
if [ -n "$running_names" ]; then
|
if [ -n "$running_names" ]; then
|
||||||
all_dstats=$(docker stats --no-stream --format "{{.Name}} {{.CPUPerc}} {{.MemUsage}}" $running_names 2>/dev/null)
|
( docker stats --no-stream --format "{{.Name}} {{.CPUPerc}} {{.MemUsage}}" $running_names > "$_mc_tmpdir/stats" 2>/dev/null ) &
|
||||||
fi
|
fi
|
||||||
|
wait
|
||||||
|
|
||||||
|
local all_dstats=""
|
||||||
|
[ -f "$_mc_tmpdir/stats" ] && all_dstats=$(cat "$_mc_tmpdir/stats")
|
||||||
|
|
||||||
printf " ${BOLD}%-2s %-11s %-8s %-7s %-8s %-8s %-6s %-7s${NC}${EL}\n" \
|
printf " ${BOLD}%-2s %-11s %-8s %-7s %-8s %-8s %-6s %-7s${NC}${EL}\n" \
|
||||||
"#" "Container" "Status" "Clients" "Up" "Down" "CPU" "RAM"
|
"#" "Container" "Status" "Clients" "Up" "Down" "CPU" "RAM"
|
||||||
@@ -3141,7 +3423,8 @@ manage_containers() {
|
|||||||
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
|
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
|
||||||
status_text="Running"
|
status_text="Running"
|
||||||
status_color="${GREEN}"
|
status_color="${GREEN}"
|
||||||
local logs=$(docker logs --tail 50 "$cname" 2>&1 | grep "STATS" | tail -1)
|
local logs=""
|
||||||
|
[ -f "$_mc_tmpdir/logs_${ci}" ] && logs=$(cat "$_mc_tmpdir/logs_${ci}")
|
||||||
if [ -n "$logs" ]; then
|
if [ -n "$logs" ]; then
|
||||||
IFS='|' read -r conn cing mc_up mc_down <<< $(echo "$logs" | awk '{
|
IFS='|' read -r conn cing mc_up mc_down <<< $(echo "$logs" | awk '{
|
||||||
cing=0; conn=0; up=""; down=""
|
cing=0; conn=0; up=""; down=""
|
||||||
@@ -3176,6 +3459,8 @@ manage_containers() {
|
|||||||
"$ci" "$cname" "$status_color" "$status_text" "${NC}" "$c_clients" "$c_up" "$c_down" "$c_cpu" "$c_ram"
|
"$ci" "$cname" "$status_color" "$status_text" "${NC}" "$c_clients" "$c_up" "$c_down" "$c_cpu" "$c_ram"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
rm -rf "$_mc_tmpdir"
|
||||||
|
|
||||||
echo -e "${EL}"
|
echo -e "${EL}"
|
||||||
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}${EL}"
|
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}${EL}"
|
||||||
local max_add=$((5 - CONTAINER_COUNT))
|
local max_add=$((5 - CONTAINER_COUNT))
|
||||||
@@ -3223,6 +3508,86 @@ manage_containers() {
|
|||||||
fi
|
fi
|
||||||
local old_count=$CONTAINER_COUNT
|
local old_count=$CONTAINER_COUNT
|
||||||
CONTAINER_COUNT=$((CONTAINER_COUNT + add_count))
|
CONTAINER_COUNT=$((CONTAINER_COUNT + add_count))
|
||||||
|
|
||||||
|
# Ask if user wants to set resource limits on new containers
|
||||||
|
local set_limits=""
|
||||||
|
local new_cpus="" new_mem=""
|
||||||
|
echo ""
|
||||||
|
read -p " Set CPU/memory limits on new container(s)? [y/N]: " set_limits < /dev/tty || true
|
||||||
|
if [[ "$set_limits" =~ ^[Yy]$ ]]; then
|
||||||
|
local cpu_cores=$(nproc 2>/dev/null || grep -c ^processor /proc/cpuinfo 2>/dev/null || echo 1)
|
||||||
|
local ram_mb=$(awk '/MemTotal/{printf "%.0f", $2/1024}' /proc/meminfo 2>/dev/null || echo 512)
|
||||||
|
local rec_cpu=$(awk -v c="$cpu_cores" 'BEGIN{v=c/2; if(v<0.5) v=0.5; printf "%.1f", v}')
|
||||||
|
local rec_mem="256m"
|
||||||
|
[ "$ram_mb" -ge 2048 ] && rec_mem="512m"
|
||||||
|
[ "$ram_mb" -ge 4096 ] && rec_mem="1g"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e " ${CYAN}───────────────────────────────────────────────────────────────${NC}"
|
||||||
|
echo -e " ${BOLD}CPU Limit${NC}"
|
||||||
|
echo -e " Limits how much processor power this container can use."
|
||||||
|
echo -e " This prevents it from slowing down other services on your system."
|
||||||
|
echo -e ""
|
||||||
|
echo -e " ${DIM}Your system has ${GREEN}${cpu_cores}${NC}${DIM} core(s).${NC}"
|
||||||
|
echo -e " ${DIM} 0.5 = half a core 1.0 = one full core${NC}"
|
||||||
|
echo -e " ${DIM} 2.0 = two cores ${cpu_cores}.0 = all cores (no limit)${NC}"
|
||||||
|
echo -e ""
|
||||||
|
echo -e " Press Enter to use the recommended default."
|
||||||
|
echo -e " ${CYAN}───────────────────────────────────────────────────────────────${NC}"
|
||||||
|
read -p " CPU limit [${rec_cpu}]: " input_cpus < /dev/tty || true
|
||||||
|
[ -z "$input_cpus" ] && input_cpus="$rec_cpu"
|
||||||
|
if [[ "$input_cpus" =~ ^[0-9]+\.?[0-9]*$ ]]; then
|
||||||
|
local cpu_ok=$(awk -v val="$input_cpus" -v max="$cpu_cores" 'BEGIN { print (val > 0 && val <= max) ? "yes" : "no" }')
|
||||||
|
if [ "$cpu_ok" = "yes" ]; then
|
||||||
|
new_cpus="$input_cpus"
|
||||||
|
echo -e " ${GREEN}✓ CPU limit: ${new_cpus} core(s)${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}Must be between 0.1 and ${cpu_cores}. Using default: ${rec_cpu}${NC}"
|
||||||
|
new_cpus="$rec_cpu"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}Invalid input. Using default: ${rec_cpu}${NC}"
|
||||||
|
new_cpus="$rec_cpu"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e " ${CYAN}───────────────────────────────────────────────────────────────${NC}"
|
||||||
|
echo -e " ${BOLD}Memory Limit${NC}"
|
||||||
|
echo -e " Maximum RAM this container can use."
|
||||||
|
echo -e " Prevents it from consuming all memory and crashing other services."
|
||||||
|
echo -e ""
|
||||||
|
echo -e " ${DIM}Your system has ${GREEN}${ram_mb} MB${NC}${DIM} RAM.${NC}"
|
||||||
|
echo -e " ${DIM} 256m = 256 MB (good for low-end systems)${NC}"
|
||||||
|
echo -e " ${DIM} 512m = 512 MB (balanced)${NC}"
|
||||||
|
echo -e " ${DIM} 1g = 1 GB (high capacity)${NC}"
|
||||||
|
echo -e ""
|
||||||
|
echo -e " Press Enter to use the recommended default."
|
||||||
|
echo -e " ${CYAN}───────────────────────────────────────────────────────────────${NC}"
|
||||||
|
read -p " Memory limit [${rec_mem}]: " input_mem < /dev/tty || true
|
||||||
|
[ -z "$input_mem" ] && input_mem="$rec_mem"
|
||||||
|
if [[ "$input_mem" =~ ^[0-9]+[mMgG]$ ]]; then
|
||||||
|
local mem_val=${input_mem%[mMgG]}
|
||||||
|
local mem_unit=${input_mem: -1}
|
||||||
|
local mem_mb_val=$mem_val
|
||||||
|
[[ "$mem_unit" =~ [gG] ]] && mem_mb_val=$((mem_val * 1024))
|
||||||
|
if [ "$mem_mb_val" -ge 64 ] && [ "$mem_mb_val" -le "$ram_mb" ]; then
|
||||||
|
new_mem="$input_mem"
|
||||||
|
echo -e " ${GREEN}✓ Memory limit: ${new_mem}${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}Must be between 64m and ${ram_mb}m. Using default: ${rec_mem}${NC}"
|
||||||
|
new_mem="$rec_mem"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}Invalid format. Using default: ${rec_mem}${NC}"
|
||||||
|
new_mem="$rec_mem"
|
||||||
|
fi
|
||||||
|
# Save per-container overrides for new containers
|
||||||
|
for i in $(seq $((old_count + 1)) $CONTAINER_COUNT); do
|
||||||
|
[ -n "$new_cpus" ] && eval "CPUS_${i}=${new_cpus}"
|
||||||
|
[ -n "$new_mem" ] && eval "MEMORY_${i}=${new_mem}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
save_settings
|
save_settings
|
||||||
for i in $(seq $((old_count + 1)) $CONTAINER_COUNT); do
|
for i in $(seq $((old_count + 1)) $CONTAINER_COUNT); do
|
||||||
local name=$(get_container_name $i)
|
local name=$(get_container_name $i)
|
||||||
@@ -3231,7 +3596,12 @@ manage_containers() {
|
|||||||
fix_volume_permissions $i
|
fix_volume_permissions $i
|
||||||
run_conduit_container $i
|
run_conduit_container $i
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo -e " ${GREEN}✓ ${name} started${NC}"
|
local c_cpu=$(get_container_cpus $i)
|
||||||
|
local c_mem=$(get_container_memory $i)
|
||||||
|
local cpu_info="" mem_info=""
|
||||||
|
[ -n "$c_cpu" ] && cpu_info=", CPU: ${c_cpu}"
|
||||||
|
[ -n "$c_mem" ] && mem_info=", Mem: ${c_mem}"
|
||||||
|
echo -e " ${GREEN}✓ ${name} started${NC}${cpu_info}${mem_info}"
|
||||||
else
|
else
|
||||||
echo -e " ${RED}✗ Failed to start ${name}${NC}"
|
echo -e " ${RED}✗ Failed to start ${name}${NC}"
|
||||||
fi
|
fi
|
||||||
@@ -3254,51 +3624,83 @@ manage_containers() {
|
|||||||
local old_count=$CONTAINER_COUNT
|
local old_count=$CONTAINER_COUNT
|
||||||
CONTAINER_COUNT=$((CONTAINER_COUNT - rm_count))
|
CONTAINER_COUNT=$((CONTAINER_COUNT - rm_count))
|
||||||
save_settings
|
save_settings
|
||||||
|
# Remove containers in parallel
|
||||||
|
local _rm_pids=() _rm_names=()
|
||||||
for i in $(seq $((CONTAINER_COUNT + 1)) $old_count); do
|
for i in $(seq $((CONTAINER_COUNT + 1)) $old_count); do
|
||||||
local name=$(get_container_name $i)
|
local name=$(get_container_name $i)
|
||||||
docker stop "$name" 2>/dev/null || true
|
_rm_names+=("$name")
|
||||||
docker rm "$name" 2>/dev/null || true
|
( docker rm -f "$name" >/dev/null 2>&1 ) &
|
||||||
echo -e " ${YELLOW}✓ ${name} removed${NC}"
|
_rm_pids+=($!)
|
||||||
|
done
|
||||||
|
for idx in "${!_rm_pids[@]}"; do
|
||||||
|
if wait "${_rm_pids[$idx]}" 2>/dev/null; then
|
||||||
|
echo -e " ${YELLOW}✓ ${_rm_names[$idx]} removed${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${RED}✗ Failed to remove ${_rm_names[$idx]}${NC}"
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
||||||
;;
|
;;
|
||||||
s)
|
s)
|
||||||
read -p " Start which container? (1-${CONTAINER_COUNT}, or 'all'): " sc_idx < /dev/tty || true
|
read -p " Start which container? (1-${CONTAINER_COUNT}, or 'all'): " sc_idx < /dev/tty || true
|
||||||
|
local sc_targets=()
|
||||||
if [ "$sc_idx" = "all" ]; then
|
if [ "$sc_idx" = "all" ]; then
|
||||||
for i in $(seq 1 $CONTAINER_COUNT); do
|
for i in $(seq 1 $CONTAINER_COUNT); do sc_targets+=($i); done
|
||||||
local name=$(get_container_name $i)
|
elif [[ "$sc_idx" =~ ^[1-5]$ ]] && [ "$sc_idx" -le "$CONTAINER_COUNT" ]; then
|
||||||
local vol=$(get_volume_name $i)
|
sc_targets+=($sc_idx)
|
||||||
if docker ps -a 2>/dev/null | grep -q "[[:space:]]${name}$"; then
|
else
|
||||||
docker start "$name" 2>/dev/null
|
echo -e " ${RED}Invalid.${NC}"
|
||||||
else
|
fi
|
||||||
|
# Batch: get all existing containers and their inspect data in one call
|
||||||
|
local existing_containers=$(docker ps -a --format '{{.Names}}' 2>/dev/null)
|
||||||
|
local all_inspect=""
|
||||||
|
local inspect_names=""
|
||||||
|
for i in "${sc_targets[@]}"; do
|
||||||
|
local cn=$(get_container_name $i)
|
||||||
|
echo "$existing_containers" | grep -q "^${cn}$" && inspect_names+=" $cn"
|
||||||
|
done
|
||||||
|
[ -n "$inspect_names" ] && all_inspect=$(docker inspect --format '{{.Name}} {{.HostConfig.NanoCpus}} {{.HostConfig.Memory}}' $inspect_names 2>/dev/null)
|
||||||
|
|
||||||
|
for i in "${sc_targets[@]}"; do
|
||||||
|
local name=$(get_container_name $i)
|
||||||
|
local vol=$(get_volume_name $i)
|
||||||
|
if echo "$existing_containers" | grep -q "^${name}$"; then
|
||||||
|
# Check if settings changed — recreate if needed
|
||||||
|
local needs_recreate=false
|
||||||
|
local want_cpus=$(get_container_cpus $i)
|
||||||
|
local want_mem=$(get_container_memory $i)
|
||||||
|
local insp_line=$(echo "$all_inspect" | grep "/${name} " 2>/dev/null)
|
||||||
|
local cur_nano=$(echo "$insp_line" | awk '{print $2}')
|
||||||
|
local cur_memb=$(echo "$insp_line" | awk '{print $3}')
|
||||||
|
local want_nano=0
|
||||||
|
[ -n "$want_cpus" ] && want_nano=$(awk -v c="$want_cpus" 'BEGIN{printf "%.0f", c*1000000000}')
|
||||||
|
local want_memb=0
|
||||||
|
if [ -n "$want_mem" ]; then
|
||||||
|
local mv=${want_mem%[mMgG]}; local mu=${want_mem: -1}
|
||||||
|
[[ "$mu" =~ [gG] ]] && want_memb=$((mv * 1073741824)) || want_memb=$((mv * 1048576))
|
||||||
|
fi
|
||||||
|
[ "${cur_nano:-0}" != "$want_nano" ] && needs_recreate=true
|
||||||
|
[ "${cur_memb:-0}" != "$want_memb" ] && needs_recreate=true
|
||||||
|
if [ "$needs_recreate" = true ]; then
|
||||||
|
echo -e " Settings changed for ${name}, recreating..."
|
||||||
|
docker rm -f "$name" 2>/dev/null || true
|
||||||
docker volume create "$vol" 2>/dev/null || true
|
docker volume create "$vol" 2>/dev/null || true
|
||||||
fix_volume_permissions $i
|
fix_volume_permissions $i
|
||||||
run_conduit_container $i
|
run_conduit_container $i
|
||||||
fi
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo -e " ${GREEN}✓ ${name} started${NC}"
|
|
||||||
else
|
else
|
||||||
echo -e " ${RED}✗ Failed to start ${name}${NC}"
|
docker start "$name" 2>/dev/null
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
elif [[ "$sc_idx" =~ ^[1-5]$ ]] && [ "$sc_idx" -le "$CONTAINER_COUNT" ]; then
|
|
||||||
local name=$(get_container_name $sc_idx)
|
|
||||||
local vol=$(get_volume_name $sc_idx)
|
|
||||||
if docker ps -a 2>/dev/null | grep -q "[[:space:]]${name}$"; then
|
|
||||||
docker start "$name" 2>/dev/null
|
|
||||||
else
|
else
|
||||||
docker volume create "$vol" 2>/dev/null || true
|
docker volume create "$vol" 2>/dev/null || true
|
||||||
fix_volume_permissions $sc_idx
|
fix_volume_permissions $i
|
||||||
run_conduit_container $sc_idx
|
run_conduit_container $i
|
||||||
fi
|
fi
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo -e " ${GREEN}✓ ${name} started${NC}"
|
echo -e " ${GREEN}✓ ${name} started${NC}"
|
||||||
else
|
else
|
||||||
echo -e " ${RED}✗ Failed to start ${name}${NC}"
|
echo -e " ${RED}✗ Failed to start ${name}${NC}"
|
||||||
fi
|
fi
|
||||||
else
|
done
|
||||||
echo -e " ${RED}Invalid.${NC}"
|
|
||||||
fi
|
|
||||||
# Ensure tracker service is running when containers are started
|
# Ensure tracker service is running when containers are started
|
||||||
setup_tracker_service 2>/dev/null || true
|
setup_tracker_service 2>/dev/null || true
|
||||||
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
||||||
@@ -3306,17 +3708,25 @@ manage_containers() {
|
|||||||
t)
|
t)
|
||||||
read -p " Stop which container? (1-${CONTAINER_COUNT}, or 'all'): " sc_idx < /dev/tty || true
|
read -p " Stop which container? (1-${CONTAINER_COUNT}, or 'all'): " sc_idx < /dev/tty || true
|
||||||
if [ "$sc_idx" = "all" ]; then
|
if [ "$sc_idx" = "all" ]; then
|
||||||
|
# Stop all containers in parallel with short timeout
|
||||||
|
local _stop_pids=()
|
||||||
|
local _stop_names=()
|
||||||
for i in $(seq 1 $CONTAINER_COUNT); do
|
for i in $(seq 1 $CONTAINER_COUNT); do
|
||||||
local name=$(get_container_name $i)
|
local name=$(get_container_name $i)
|
||||||
if docker stop "$name" 2>/dev/null; then
|
_stop_names+=("$name")
|
||||||
echo -e " ${YELLOW}✓ ${name} stopped${NC}"
|
( docker stop -t 3 "$name" >/dev/null 2>&1 ) &
|
||||||
|
_stop_pids+=($!)
|
||||||
|
done
|
||||||
|
for idx in "${!_stop_pids[@]}"; do
|
||||||
|
if wait "${_stop_pids[$idx]}" 2>/dev/null; then
|
||||||
|
echo -e " ${YELLOW}✓ ${_stop_names[$idx]} stopped${NC}"
|
||||||
else
|
else
|
||||||
echo -e " ${YELLOW} ${name} was not running${NC}"
|
echo -e " ${YELLOW} ${_stop_names[$idx]} was not running${NC}"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
elif [[ "$sc_idx" =~ ^[1-5]$ ]] && [ "$sc_idx" -le "$CONTAINER_COUNT" ]; then
|
elif [[ "$sc_idx" =~ ^[1-5]$ ]] && [ "$sc_idx" -le "$CONTAINER_COUNT" ]; then
|
||||||
local name=$(get_container_name $sc_idx)
|
local name=$(get_container_name $sc_idx)
|
||||||
if docker stop "$name" 2>/dev/null; then
|
if docker stop -t 3 "$name" 2>/dev/null; then
|
||||||
echo -e " ${YELLOW}✓ ${name} stopped${NC}"
|
echo -e " ${YELLOW}✓ ${name} stopped${NC}"
|
||||||
else
|
else
|
||||||
echo -e " ${YELLOW} ${name} was not running${NC}"
|
echo -e " ${YELLOW} ${name} was not running${NC}"
|
||||||
@@ -3328,6 +3738,7 @@ manage_containers() {
|
|||||||
;;
|
;;
|
||||||
x)
|
x)
|
||||||
read -p " Restart which container? (1-${CONTAINER_COUNT}, or 'all'): " sc_idx < /dev/tty || true
|
read -p " Restart which container? (1-${CONTAINER_COUNT}, or 'all'): " sc_idx < /dev/tty || true
|
||||||
|
local xc_targets=()
|
||||||
if [ "$sc_idx" = "all" ]; then
|
if [ "$sc_idx" = "all" ]; then
|
||||||
local persist_dir="$INSTALL_DIR/traffic_stats"
|
local persist_dir="$INSTALL_DIR/traffic_stats"
|
||||||
if [ -s "$persist_dir/cumulative_data" ] || [ -s "$persist_dir/cumulative_ips" ]; then
|
if [ -s "$persist_dir/cumulative_data" ] || [ -s "$persist_dir/cumulative_ips" ]; then
|
||||||
@@ -3337,27 +3748,71 @@ manage_containers() {
|
|||||||
[ -s "$persist_dir/geoip_cache" ] && cp "$persist_dir/geoip_cache" "$persist_dir/geoip_cache.bak"
|
[ -s "$persist_dir/geoip_cache" ] && cp "$persist_dir/geoip_cache" "$persist_dir/geoip_cache.bak"
|
||||||
echo -e " ${GREEN}✓ Tracker data snapshot saved${NC}"
|
echo -e " ${GREEN}✓ Tracker data snapshot saved${NC}"
|
||||||
fi
|
fi
|
||||||
for i in $(seq 1 $CONTAINER_COUNT); do
|
for i in $(seq 1 $CONTAINER_COUNT); do xc_targets+=($i); done
|
||||||
local name=$(get_container_name $i)
|
elif [[ "$sc_idx" =~ ^[1-5]$ ]] && [ "$sc_idx" -le "$CONTAINER_COUNT" ]; then
|
||||||
if docker restart "$name" 2>/dev/null; then
|
xc_targets+=($sc_idx)
|
||||||
|
else
|
||||||
|
echo -e " ${RED}Invalid.${NC}"
|
||||||
|
fi
|
||||||
|
# Batch: get all existing containers and inspect data in one call
|
||||||
|
local existing_containers=$(docker ps -a --format '{{.Names}}' 2>/dev/null)
|
||||||
|
local all_inspect=""
|
||||||
|
local inspect_names=""
|
||||||
|
for i in "${xc_targets[@]}"; do
|
||||||
|
local cn=$(get_container_name $i)
|
||||||
|
echo "$existing_containers" | grep -q "^${cn}$" && inspect_names+=" $cn"
|
||||||
|
done
|
||||||
|
[ -n "$inspect_names" ] && all_inspect=$(docker inspect --format '{{.Name}} {{join .Args " "}} |||{{.HostConfig.NanoCpus}} {{.HostConfig.Memory}}' $inspect_names 2>/dev/null)
|
||||||
|
|
||||||
|
for i in "${xc_targets[@]}"; do
|
||||||
|
local name=$(get_container_name $i)
|
||||||
|
local vol=$(get_volume_name $i)
|
||||||
|
local needs_recreate=false
|
||||||
|
local want_cpus=$(get_container_cpus $i)
|
||||||
|
local want_mem=$(get_container_memory $i)
|
||||||
|
local want_mc=$(get_container_max_clients $i)
|
||||||
|
local want_bw=$(get_container_bandwidth $i)
|
||||||
|
if echo "$existing_containers" | grep -q "^${name}$"; then
|
||||||
|
local insp_line=$(echo "$all_inspect" | grep "/${name} " 2>/dev/null)
|
||||||
|
local cur_args=$(echo "$insp_line" | sed 's/.*\/'"$name"' //' | sed 's/ |||.*//')
|
||||||
|
local cur_mc=$(echo "$cur_args" | sed -n 's/.*--max-clients \([^ ]*\).*/\1/p' 2>/dev/null)
|
||||||
|
local cur_bw=$(echo "$cur_args" | sed -n 's/.*--bandwidth \([^ ]*\).*/\1/p' 2>/dev/null)
|
||||||
|
[ "$cur_mc" != "$want_mc" ] && needs_recreate=true
|
||||||
|
[ "$cur_bw" != "$want_bw" ] && needs_recreate=true
|
||||||
|
local cur_nano=$(echo "$insp_line" | sed 's/.*|||//' | awk '{print $1}')
|
||||||
|
local cur_memb=$(echo "$insp_line" | sed 's/.*|||//' | awk '{print $2}')
|
||||||
|
local want_nano=0
|
||||||
|
[ -n "$want_cpus" ] && want_nano=$(awk -v c="$want_cpus" 'BEGIN{printf "%.0f", c*1000000000}')
|
||||||
|
local want_memb=0
|
||||||
|
if [ -n "$want_mem" ]; then
|
||||||
|
local mv=${want_mem%[mMgG]}; local mu=${want_mem: -1}
|
||||||
|
[[ "$mu" =~ [gG] ]] && want_memb=$((mv * 1073741824)) || want_memb=$((mv * 1048576))
|
||||||
|
fi
|
||||||
|
[ "${cur_nano:-0}" != "$want_nano" ] && needs_recreate=true
|
||||||
|
[ "${cur_memb:-0}" != "$want_memb" ] && needs_recreate=true
|
||||||
|
fi
|
||||||
|
if [ "$needs_recreate" = true ]; then
|
||||||
|
echo -e " Settings changed for ${name}, recreating..."
|
||||||
|
docker rm -f "$name" 2>/dev/null || true
|
||||||
|
docker volume create "$vol" 2>/dev/null || true
|
||||||
|
fix_volume_permissions $i
|
||||||
|
run_conduit_container $i
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e " ${GREEN}✓ ${name} recreated with new settings${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${RED}✗ Failed to recreate ${name}${NC}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if docker restart -t 3 "$name" 2>/dev/null; then
|
||||||
echo -e " ${GREEN}✓ ${name} restarted${NC}"
|
echo -e " ${GREEN}✓ ${name} restarted${NC}"
|
||||||
else
|
else
|
||||||
echo -e " ${RED}✗ Failed to restart ${name}${NC}"
|
echo -e " ${RED}✗ Failed to restart ${name}${NC}"
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
# Restart tracker to pick up new container state
|
|
||||||
if command -v systemctl &>/dev/null && systemctl is-active --quiet conduit-tracker.service 2>/dev/null; then
|
|
||||||
systemctl restart conduit-tracker.service 2>/dev/null || true
|
|
||||||
fi
|
fi
|
||||||
elif [[ "$sc_idx" =~ ^[1-5]$ ]] && [ "$sc_idx" -le "$CONTAINER_COUNT" ]; then
|
done
|
||||||
local name=$(get_container_name $sc_idx)
|
# Restart tracker to pick up new container state
|
||||||
if docker restart "$name" 2>/dev/null; then
|
if command -v systemctl &>/dev/null && systemctl is-active --quiet conduit-tracker.service 2>/dev/null; then
|
||||||
echo -e " ${GREEN}✓ ${name} restarted${NC}"
|
systemctl restart conduit-tracker.service 2>/dev/null || true
|
||||||
else
|
|
||||||
echo -e " ${RED}✗ Failed to restart ${name}${NC}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo -e " ${RED}Invalid.${NC}"
|
|
||||||
fi
|
fi
|
||||||
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
||||||
;;
|
;;
|
||||||
@@ -3547,13 +4002,19 @@ TELEGRAM_DAILY_SUMMARY=${TELEGRAM_DAILY_SUMMARY:-true}
|
|||||||
TELEGRAM_WEEKLY_SUMMARY=${TELEGRAM_WEEKLY_SUMMARY:-true}
|
TELEGRAM_WEEKLY_SUMMARY=${TELEGRAM_WEEKLY_SUMMARY:-true}
|
||||||
TELEGRAM_SERVER_LABEL="${TELEGRAM_SERVER_LABEL:-}"
|
TELEGRAM_SERVER_LABEL="${TELEGRAM_SERVER_LABEL:-}"
|
||||||
TELEGRAM_START_HOUR=${TELEGRAM_START_HOUR:-0}
|
TELEGRAM_START_HOUR=${TELEGRAM_START_HOUR:-0}
|
||||||
|
DOCKER_CPUS=${DOCKER_CPUS:-}
|
||||||
|
DOCKER_MEMORY=${DOCKER_MEMORY:-}
|
||||||
EOF
|
EOF
|
||||||
# Save per-container overrides
|
# Save per-container overrides
|
||||||
for i in $(seq 1 5); do
|
for i in $(seq 1 5); do
|
||||||
local mc_var="MAX_CLIENTS_${i}"
|
local mc_var="MAX_CLIENTS_${i}"
|
||||||
local bw_var="BANDWIDTH_${i}"
|
local bw_var="BANDWIDTH_${i}"
|
||||||
|
local cpu_var="CPUS_${i}"
|
||||||
|
local mem_var="MEMORY_${i}"
|
||||||
[ -n "${!mc_var}" ] && echo "${mc_var}=${!mc_var}" >> "$INSTALL_DIR/settings.conf"
|
[ -n "${!mc_var}" ] && echo "${mc_var}=${!mc_var}" >> "$INSTALL_DIR/settings.conf"
|
||||||
[ -n "${!bw_var}" ] && echo "${bw_var}=${!bw_var}" >> "$INSTALL_DIR/settings.conf"
|
[ -n "${!bw_var}" ] && echo "${bw_var}=${!bw_var}" >> "$INSTALL_DIR/settings.conf"
|
||||||
|
[ -n "${!cpu_var}" ] && echo "${cpu_var}=${!cpu_var}" >> "$INSTALL_DIR/settings.conf"
|
||||||
|
[ -n "${!mem_var}" ] && echo "${mem_var}=${!mem_var}" >> "$INSTALL_DIR/settings.conf"
|
||||||
done
|
done
|
||||||
chmod 600 "$INSTALL_DIR/settings.conf" 2>/dev/null || true
|
chmod 600 "$INSTALL_DIR/settings.conf" 2>/dev/null || true
|
||||||
}
|
}
|
||||||
@@ -4615,6 +5076,7 @@ show_settings_menu() {
|
|||||||
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
|
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
|
||||||
echo -e " 1. ⚙️ Change settings (max-clients, bandwidth)"
|
echo -e " 1. ⚙️ Change settings (max-clients, bandwidth)"
|
||||||
echo -e " 2. 📊 Set data usage cap"
|
echo -e " 2. 📊 Set data usage cap"
|
||||||
|
echo -e " l. 🖥️ Set resource limits (CPU, memory)"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " 3. 💾 Backup node key"
|
echo -e " 3. 💾 Backup node key"
|
||||||
echo -e " 4. 📥 Restore node key"
|
echo -e " 4. 📥 Restore node key"
|
||||||
@@ -4653,6 +5115,11 @@ show_settings_menu() {
|
|||||||
read -n 1 -s -r -p "Press any key to return..." < /dev/tty || true
|
read -n 1 -s -r -p "Press any key to return..." < /dev/tty || true
|
||||||
redraw=true
|
redraw=true
|
||||||
;;
|
;;
|
||||||
|
l|L)
|
||||||
|
change_resource_limits
|
||||||
|
read -n 1 -s -r -p "Press any key to return..." < /dev/tty || true
|
||||||
|
redraw=true
|
||||||
|
;;
|
||||||
3)
|
3)
|
||||||
backup_key
|
backup_key
|
||||||
read -n 1 -s -r -p "Press any key to return..." < /dev/tty || true
|
read -n 1 -s -r -p "Press any key to return..." < /dev/tty || true
|
||||||
|
|||||||
Reference in New Issue
Block a user