16 Commits

Author SHA1 Message Date
juewuy
1afb261d0e ~优化定时任务 2026-02-08 20:13:55 +08:00
juewuy
32d73c18c4 ~1.9.4rc6 pkg 2026-02-08 19:38:01 +08:00
juewuy
cb9d5a783b ~修复保守模式部分情况下反复重启的bug 2026-02-08 19:31:23 +08:00
juewuy
c4bdd18195 ~修复ddns工具的一些bug 2026-02-08 19:14:45 +08:00
juewuy
7f0b0fa870 ~bug fix 2026-02-08 18:36:50 +08:00
juewuy
d5d9fab8e0 ~bug fix 2026-02-08 18:28:05 +08:00
juewuy
053f05d394 ~修复docker相关bug 2026-02-08 18:25:47 +08:00
juewuy
fc1c3c4415 ~bug fix 2026-02-08 18:05:01 +08:00
juewuy
6a1d4086f3 ~1.9.4r5 pkg 2026-02-04 19:05:22 +08:00
juewuy
b59da3be8a ~fix 2026-02-04 18:53:46 +08:00
juewuy
76efd54d03 ~bug fix 2026-02-04 18:52:11 +08:00
juewuy
ace8b08407 ~优化容器部署说明,修复持久化问题 2026-02-04 18:46:25 +08:00
juewuy
f70e642fea ~修复部分情况下自启状态显示不正确的bug 2026-02-04 18:27:29 +08:00
juewuy
614bc696bb ~继续优化定时任务功能 2026-02-04 18:20:43 +08:00
juewuy
cd7d4232b6 ~修复因.start_error失败标记导致的部分bug 2026-02-04 17:59:20 +08:00
juewuy
fd4ca02ff3 ~1.9.4r4.1 pkg 2026-02-02 21:50:43 +08:00
18 changed files with 90 additions and 48 deletions

View File

@@ -57,8 +57,7 @@ RUN apk add --no-cache \
ca-certificates \ ca-certificates \
tzdata \ tzdata \
nftables \ nftables \
iproute2 \ iproute2
dcron
RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \ RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
echo "${TZ}" > /etc/timezone echo "${TZ}" > /etc/timezone

Binary file not shown.

View File

@@ -1,4 +1,4 @@
meta_v=v1.19.17 meta_v=v1.19.17
singboxr_v=1.13.0-alpha.27 singboxr_v=1.13.0-alpha.27
versionsh=1.9.4rc4 versionsh=1.9.4rc6
GeoIP_v=20251205 GeoIP_v=20251205

View File

@@ -57,6 +57,7 @@ docker run -d \
--cap-add NET_ADMIN \ --cap-add NET_ADMIN \
--cap-add NET_RAW \ --cap-add NET_RAW \
--cap-add SYS_ADMIN \ --cap-add SYS_ADMIN \
--sysctl net.ipv4.ip_forward=1 \
--device /dev/net/tun:/dev/net/tun \ --device /dev/net/tun:/dev/net/tun \
--restart unless-stopped \ --restart unless-stopped \
juewuy/shellcrash:latest juewuy/shellcrash:latest
@@ -87,14 +88,10 @@ mkdir -p /root/ShellCrash
```shell ```shell
docker run -d \ docker run -d \
……………… ………………
-v /root/ShellCrash:/etc/ShellCrash \ -v shellcrash_configs:/etc/ShellCrash/configs \
……………… ………………
``` ```
------
------ ------
## Compose DeploymentCompose部署 ## Compose DeploymentCompose部署
@@ -102,8 +99,8 @@ docker run -d \
### 1. 创建宿主机目录并进入目录 ### 1. 创建宿主机目录并进入目录
```shell ```shell
mkdir -p /root/ShellCrash mkdir -p /tmp/ShellCrash
cd /root/ShellCrash cd /tmp/ShellCrash
``` ```
### 2. 下载Compose模版 ### 2. 下载Compose模版
@@ -126,8 +123,29 @@ docker compose up -d
------ ------
### Notes ## Delete移除容器镜像或删除卷
### Docker删除容器
```shell
docker rm -f shellcrash
```
### Docker删除卷
```shell
docker volume rm shellcrash_configs
```
### Compose删除容器&卷
```shell
docker-compose down -v
```
## Notes
- 内置公网防火墙功能无法管理宿主机网络请自行做好宿主机7890/9999端口的网络防护
- 旁路由模式需要宿主机支持 `TUN` - 旁路由模式需要宿主机支持 `TUN`
- macvlan 网络下宿主机默认无法直接访问容器 IP - macvlan 网络下宿主机默认无法直接访问容器 IP
- 透明代理场景可能需要额外的网络规划 - 透明代理场景可能需要额外的网络规划

View File

@@ -14,11 +14,15 @@ services:
devices: devices:
- "/dev/net/tun:/dev/net/tun" - "/dev/net/tun:/dev/net/tun"
sysctls: sysctls:
net.ipv4.ip_forward: 1 - net.ipv4.ip_forward: 1
# - net.ipv6.conf.all.forwarding=1
volumes: volumes:
- /etc/ShellCrash:/root/ShellCrash - shellcrash_configs:/etc/ShellCrash/configs:rw
restart: unless-stopped restart: unless-stopped
volumes:
shellcrash_configs:
networks: networks:
macvlan_lan: macvlan_lan:
name: macvlan_lan name: macvlan_lan

View File

@@ -3,6 +3,7 @@ check_autostart(){
[ ! -f "$CRASHDIR"/.dis_startup ] && return 0 [ ! -f "$CRASHDIR"/.dis_startup ] && return 0
elif [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ]; then elif [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ]; then
[ -n "$(find /etc/rc.d -name '*shellcrash')" ] && return 0 [ -n "$(find /etc/rc.d -name '*shellcrash')" ] && return 0
[ ! -f "$CRASHDIR"/.dis_startup ] && return 0
elif ckcmd systemctl; then elif ckcmd systemctl; then
[ "$(systemctl is-enabled shellcrash.service 2>&1)" = enabled ] && return 0 [ "$(systemctl is-enabled shellcrash.service 2>&1)" = enabled ] && return 0
elif grep -q 's6' /proc/1/comm; then elif grep -q 's6' /proc/1/comm; then

View File

@@ -16,7 +16,7 @@ routing_mark=$((fwmark + 2))
[ -z "$dns_nameserver" ] && { [ -z "$dns_nameserver" ] && {
dns_nameserver='223.5.5.5, 1.2.4.8' dns_nameserver='223.5.5.5, 1.2.4.8'
cat /proc/net/udp | grep -q '0035' && dns_nameserver='127.0.0.1' netstat -ntlup 2>/dev/null | grep -q '127.0.0.1:53' && dns_nameserver='127.0.0.1'
} }
[ -z "$dns_fallback" ] && dns_fallback="1.1.1.1, 8.8.8.8" [ -z "$dns_fallback" ] && dns_fallback="1.1.1.1, 8.8.8.8"
[ -z "$dns_resolver" ] && dns_resolver="223.5.5.5, 2400:3200::1" [ -z "$dns_resolver" ] && dns_resolver="223.5.5.5, 2400:3200::1"

View File

@@ -10,17 +10,19 @@ touch "$tmpcron"
cronadd() { #定时任务工具 cronadd() { #定时任务工具
if crontab -h 2>&1 | grep -q '\-l'; then if crontab -h 2>&1 | grep -q '\-l'; then
crontab "$1" crontab "$1"
else elif [ -f "$crondir/$USER" ];then
cat "$1" >"$crondir"/"$USER" && cru a REFRESH "0 0 1 1 * /bin/true" 2>/dev/null cat "$1" >"$crondir"/"$USER" && cru a REFRESH "0 0 1 1 * /bin/true" 2>/dev/null
else
echo "找不到可用的crond或者crontab应用No available crond or crontab application can be found!"
fi fi
} }
cronload() { #定时任务工具 cronload() { #定时任务工具
if [ -f "$crondir/$USER" ];then if crontab -h 2>&1 | grep -q '\-l'; then
cat "$crondir"/"$USER" 2>/dev/null
elif crontab -h 2>&1 | grep -q '\-l'; then
crontab -l crontab -l
elif [ -f "$crondir/$USER" ];then
cat "$crondir"/"$USER" 2>/dev/null
else else
echo "找不到可用的crond或者crontab应用No available crond or crontab application can be found!" return 1
fi fi
} }
cronset() { #定时任务设置 cronset() { #定时任务设置
@@ -34,5 +36,4 @@ cronset() { #定时任务设置
else else
rm -f "$tmpcron" rm -f "$tmpcron"
fi fi
sleep 1
} }

View File

@@ -5,4 +5,5 @@ set_profile() {
echo "alias ${my_alias}=\"$shtype $CRASHDIR/menu.sh\"" >>"$1" #设置快捷命令环境变量 echo "alias ${my_alias}=\"$shtype $CRASHDIR/menu.sh\"" >>"$1" #设置快捷命令环境变量
sed -i '/export CRASHDIR=*/'d "$1" sed -i '/export CRASHDIR=*/'d "$1"
echo "export CRASHDIR=\"$CRASHDIR\"" >>"$1" #设置路径环境变量 echo "export CRASHDIR=\"$CRASHDIR\"" >>"$1" #设置路径环境变量
. "$1" >/dev/null 2>&1 || true
} }

View File

@@ -97,6 +97,7 @@ ckstatus() { #脚本启动前检查
userguide=1 userguide=1
setconfig userguide 1 setconfig userguide 1
. "$CRASHDIR"/menus/8_tools.sh && userguide . "$CRASHDIR"/menus/8_tools.sh && userguide
. "$CRASHDIR"/configs/ShellCrash.cfg
fi fi
#检查执行权限 #检查执行权限
[ ! -x "$CRASHDIR"/start.sh ] && chmod +x "$CRASHDIR"/start.sh [ ! -x "$CRASHDIR"/start.sh ] && chmod +x "$CRASHDIR"/start.sh

View File

@@ -7,7 +7,7 @@ bot_tg_start(){
bot_tg_cron bot_tg_cron
} }
bot_tg_stop(){ bot_tg_stop(){
cronset 'TG_BOT守护进程' cronload | grep -q 'TG_BOT' && cronset 'TG_BOT'
[ -f "$TMPDIR/bot_tg.pid" ] && kill -TERM "$(cat "$TMPDIR/bot_tg.pid")" 2>/dev/null [ -f "$TMPDIR/bot_tg.pid" ] && kill -TERM "$(cat "$TMPDIR/bot_tg.pid")" 2>/dev/null
killall bot_tg.sh 2>/dev/null killall bot_tg.sh 2>/dev/null
rm -f "$TMPDIR/bot_tg.pid" rm -f "$TMPDIR/bot_tg.pid"

View File

@@ -59,16 +59,21 @@ set_ddns() {
} }
set_ddns_service() { set_ddns_service() {
services_dir=/etc/ddns/"$serv" services_dir=/etc/ddns/"$serv"
[ -s "$services_dir" ] || services_dir=/etc/ddns/services
[ -s "$services_dir" ] || services_dir=/usr/share/ddns/list [ -s "$services_dir" ] || services_dir=/usr/share/ddns/list
[ -s "$services_dir" ] || {
echo -e "\033[33m未找到DDNS列表文件尝试在线获取……\033[0m"
ddns service update >/dev/null || echo -e "\033[31m下载失败请重试\033[0m"
}
echo ----------------------------------------------- echo -----------------------------------------------
echo -e "\033[32m请选择服务提供商\033[0m" echo -e "\033[32m请选择服务提供商\033[0m"
cat "$services_dir" | grep -v '^#' | awk '{print " "NR" " $1}' cat "$services_dir" | grep -vE '^#|^[[:space:]]*$' | awk '{print " "NR" " $1}'
nr=$(cat "$services_dir" | grep -v '^#' | wc -l) nr=$(cat "$services_dir" | grep -vE '^#|^[[:space:]]*$' | wc -l)
read -p "请输入对应数字 > " num read -p "请输入对应数字 > " num
if [ -z "$num" ]; then if [ -z "$num" ]; then
i= i=
elif [ "$num" -gt 0 -a "$num" -lt $nr ]; then elif [ "$num" -gt 0 -a "$num" -lt $nr ]; then
service_name=$(cat "$services_dir" | grep -v '^#' | awk '{print $1}' | sed -n "$num"p | sed 's/"//g') service_name=$(cat "$services_dir" | grep -vE '^#|^[[:space:]]*$' | awk '{print $1}' | sed -n "$num"p | sed 's/"//g')
service=$(echo $service_name | sed 's/\./_/g') service=$(echo $service_name | sed 's/\./_/g')
set_ddns set_ddns
else else

View File

@@ -37,7 +37,7 @@ case "$1" in
start) start)
[ -n "$(pidof CrashCore)" ] && $0 stop #禁止多实例 [ -n "$(pidof CrashCore)" ] && $0 stop #禁止多实例
stop_firewall #清理路由策略 stop_firewall #清理路由策略
rm -f "CRASHDIR"/.start_error #移除自启失败标记 rm -f "$CRASHDIR"/\.start_error #移除自启失败标记
#使用不同方式启动服务 #使用不同方式启动服务
if [ "$firewall_area" = "5" ]; then #主旁转发 if [ "$firewall_area" = "5" ]; then #主旁转发
. "$CRASHDIR"/starts/fw_start.sh . "$CRASHDIR"/starts/fw_start.sh
@@ -67,10 +67,10 @@ start)
stop) stop)
logger ShellCrash服务即将关闭…… logger ShellCrash服务即将关闭……
[ -n "$(pidof CrashCore)" ] && web_save #保存面板配置 [ -n "$(pidof CrashCore)" ] && web_save #保存面板配置
#删除守护进程&面板配置自动保存 #清理定时任务
cronset '保守模式守护进程' cronload | grep -vE '^$|start_legacy_wd.sh|运行时每' > "$TMPDIR"/cron_tmp
cronset '运行时每' cronadd "$TMPDIR"/cron_tmp
cronset '流媒体预解析' rm -f "$TMPDIR"/cron_tmp
#停止tg_bot #停止tg_bot
. "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_stop . "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_stop
#多种方式结束进程 #多种方式结束进程

View File

@@ -21,8 +21,6 @@ if [ -n "$test" -o -n "$(pidof CrashCore)" ]; then
[ "$start_old" = "ON" ] && [ ! -L "$TMPDIR"/CrashCore ] && rm -f "$TMPDIR"/CrashCore #删除缓存目录内核文件 [ "$start_old" = "ON" ] && [ ! -L "$TMPDIR"/CrashCore ] && rm -f "$TMPDIR"/CrashCore #删除缓存目录内核文件
. "$CRASHDIR"/starts/fw_start.sh #配置防火墙流量劫持 . "$CRASHDIR"/starts/fw_start.sh #配置防火墙流量劫持
date +%s >"$TMPDIR"/crash_start_time #标记启动时间 date +%s >"$TMPDIR"/crash_start_time #标记启动时间
#TG机器人守护进程
[ "$bot_tg_service" = ON ] && . "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_cron
#后台还原面板配置 #后台还原面板配置
[ -s "$CRASHDIR"/configs/web_save ] && { [ -s "$CRASHDIR"/configs/web_save ] && {
. "$CRASHDIR"/libs/web_restore.sh . "$CRASHDIR"/libs/web_restore.sh
@@ -35,12 +33,14 @@ if [ -n "$test" -o -n "$(pidof CrashCore)" ]; then
} & } &
ckcmd mtd_storage.sh && mtd_storage.sh save >/dev/null 2>&1 #Padavan保存/etc/storage ckcmd mtd_storage.sh && mtd_storage.sh save >/dev/null 2>&1 #Padavan保存/etc/storage
#加载定时任务 #加载定时任务
[ -s "$CRASHDIR"/task/cron ] && cronadd "$CRASHDIR"/task/cron cronload | grep -v '^$' > "$TMPDIR"/cron_tmp
[ -s "$CRASHDIR"/task/running ] && { [ -s "$CRASHDIR"/task/cron ] && cat "$CRASHDIR"/task/cron >> "$TMPDIR"/cron_tmp
cronset '运行时每' [ -s "$CRASHDIR"/task/running ] && cat "$CRASHDIR"/task/running >> "$TMPDIR"/cron_tmp
cronadd "$CRASHDIR"/task/running [ "$bot_tg_service" = ON ] && echo "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh bot_tg #ShellCrash-TG_BOT守护进程" >> "$TMPDIR"/cron_tmp
} [ "$start_old" = ON ] && echo "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh shellcrash #ShellCrash保守模式守护进程" >> "$TMPDIR"/cron_tmp
[ "$start_old" = "ON" ] && cronset '保守模式守护进程' "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh shellcrash #ShellCrash保守模式守护进程" awk '!x[$0]++' "$TMPDIR"/cron_tmp > "$TMPDIR"/cron_tmp2 #删除重复行
cronadd "$TMPDIR"/cron_tmp2
rm -f "$TMPDIR"/cron_tmp "$TMPDIR"/cron_tmp2
#加载条件任务 #加载条件任务
[ -s "$CRASHDIR"/task/afstart ] && { . "$CRASHDIR"/task/afstart; } & [ -s "$CRASHDIR"/task/afstart ] && { . "$CRASHDIR"/task/afstart; } &
[ -s "$CRASHDIR"/task/affirewall -a -s /etc/init.d/firewall -a ! -f /etc/init.d/firewall.bak ] && { [ -s "$CRASHDIR"/task/affirewall -a -s /etc/init.d/firewall -a ! -f /etc/init.d/firewall.bak ] && {

View File

@@ -8,7 +8,7 @@
[ ! -f "$TMPDIR" ] && mkdir -p "$TMPDIR" [ ! -f "$TMPDIR" ] && mkdir -p "$TMPDIR"
#当上次启动失败时终止自启动 #当上次启动失败时终止自启动
[ -f "CRASHDIR"/.start_error ] && exit 1 [ -f "$CRASHDIR"/.start_error ] && exit 1
#加载工具 #加载工具
. "$CRASHDIR"/libs/check_cmd.sh . "$CRASHDIR"/libs/check_cmd.sh
. "$CRASHDIR"/libs/check_target.sh . "$CRASHDIR"/libs/check_target.sh

View File

@@ -41,6 +41,8 @@ get_core_config() { #下载内核配置文件
fi fi
Https="${Server}/sub?target=${target}&${Server_ua}=${user_agent}&insert=true&new_name=true&scv=true&udp=true&${urlencodeUrl}" Https="${Server}/sub?target=${target}&${Server_ua}=${user_agent}&insert=true&new_name=true&scv=true&udp=true&${urlencodeUrl}"
url_type=true url_type=true
else
Https=$(echo $Https | sed 's/\\&/\&/g') #还原转义
fi fi
#输出 #输出
echo "-----------------------------------------------" echo "-----------------------------------------------"

View File

@@ -1,18 +1,28 @@
[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd) [ -z "$CRASHDIR" ] && CRASHDIR=$(cd "$(dirname "$0")"/.. && pwd)
PIDFILE="/tmp/ShellCrash/$1.pid" PIDFILE="/tmp/ShellCrash/$1.pid"
[ -f "$CRASHDIR"/.start_error ] && [ ! -f /tmp/ShellCrash/crash_start_time ] && exit 1 #当启动失败后禁止开机自启动
if [ -f "$PIDFILE" ]; then if [ -f "$PIDFILE" ]; then
PID="$(cat "$PIDFILE")" PID="$(cat "$PIDFILE")"
if [ -n "$PID" ] && [ -d "/proc/$PID" ]; then if [ -n "$PID" ] && [ "$PID" -eq "$PID" ] 2>/dev/null; then
if kill -0 "$PID" 2>/dev/null || [ -d "/proc/$PID" ]; then
return 0 return 0
fi fi
fi
#如果没有进程则拉起
if [ "$1" = shellcrash ];then
"$CRASHDIR"/start.sh start
else else
. "$CRASHDIR"/starts/start_legacy.sh rm -f "$PIDFILE"
start_legacy "$CRASHDIR/menus/bot_tg.sh" "$1" fi
fi fi
#如果没有进程则拉起
LOCKDIR="/tmp/ShellCrash/start_$1.lock"
if mkdir "$LOCKDIR" 2>/dev/null; then
if [ "$1" = "shellcrash" ]; then
"$CRASHDIR"/start.sh start
else
[ -f "$CRASHDIR/starts/start_legacy.sh" ] && . "$CRASHDIR/starts/start_legacy.sh"
start_legacy "$CRASHDIR/menus/bot_tg.sh" "$1"
fi
rm -d "$LOCKDIR" 2>/dev/null
fi

View File

@@ -1 +1 @@
1.9.4rc4 1.9.4rc6