diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml
new file mode 100644
index 00000000..16d515aa
--- /dev/null
+++ b/.github/workflows/docker.yaml
@@ -0,0 +1,50 @@
+name: Build Docker image for ShellCrash
+
+on:
+ push:
+ branches: [ master ]
+ workflow_dispatch:
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+ with:
+ fetch-depth: 1
+
+ - name: Read version
+ id: read_version
+ run: echo "VERSION=$(cat version)" >> $GITHUB_ENV
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Login to Docker Hub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+ - name: Build and push (multi-arch)
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ file: Dockerfile
+ platforms: |
+ linux/386
+ linux/amd64
+ linux/arm64
+ linux/arm/v7
+ push: true
+ tags: |
+ ${{ secrets.DOCKERHUB_USERNAME }}/shellcrash:latest
+ ${{ secrets.DOCKERHUB_USERNAME }}/shellcrash:${{ env.VERSION }}
diff --git a/.github/workflows/update_meta_core.yaml b/.github/workflows/update_meta_core.yaml
index 923897bc..9f6c58a7 100644
--- a/.github/workflows/update_meta_core.yaml
+++ b/.github/workflows/update_meta_core.yaml
@@ -176,7 +176,7 @@ jobs:
- name: Zip core by tar
run: |
- for arch in amd64 armv5 armv7 arm64 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
+ for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
[ ! -f ./tmp/linux-${arch}/meta ] && continue
mv -f ./tmp/linux-${arch}/meta ./tmp/CrashCore
chmod +x ./tmp/CrashCore
diff --git a/.github/workflows/update_singbox_core.yaml b/.github/workflows/update_singbox_core.yaml
index 120a9ed8..c080b5de 100644
--- a/.github/workflows/update_singbox_core.yaml
+++ b/.github/workflows/update_singbox_core.yaml
@@ -196,7 +196,7 @@ jobs:
- name: Zip core by tar
run: |
- for arch in amd64 armv5 armv7 arm64 mips-softfloat mipsel-hardfloat mipsel-softfloat;do
+ for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsel-hardfloat mipsel-softfloat;do
[ ! -f ./tmp/linux-${arch}/sing-box ] && continue
mv -f ./tmp/linux-${arch}/sing-box ./tmp/CrashCore
chmod +x ./tmp/CrashCore
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..2b6e6362
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,81 @@
+############################
+# Stage 1: builder
+############################
+FROM alpine:latest AS builder
+
+ARG TARGETPLATFORM
+ARG TZ=Asia/Shanghai
+ARG S6_OVERLAY_V=v3.2.1.0
+
+RUN apk add --no-cache curl tzdata
+
+# 时区
+RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
+ echo "${TZ}" > /etc/timezone
+
+WORKDIR /build
+
+#安装脚本相关文件
+COPY ShellCrash.tar.gz /tmp/ShellCrash.tar.gz
+RUN set -eux; \
+ mkdir -p /tmp/SC_tmp; \
+ tar -zxf /tmp/ShellCrash.tar.gz -C /tmp/SC_tmp; \
+ export systype=container; \
+ export CRASHDIR=/etc/ShellCrash; \
+ /bin/sh /tmp/SC_tmp/init.sh
+
+#获取内核及s6文件
+RUN set -eux; \
+ case "$TARGETPLATFORM" in \
+ linux/amd64) K=amd64 S=x86_64;; \
+ linux/arm64) K=arm64 S=aarch64;; \
+ linux/arm/v7) K=armv7 S=arm;; \
+ linux/386) K=386 S=i486;; \
+ *) echo "unsupported $TARGETPLATFORM" && exit 1 ;; \
+ esac; \
+ curl -fsSL "https://github.com/juewuy/ShellCrash/raw/update/bin/meta/clash-linux-${K}.tar.gz" -o /tmp/CrashCore.tar.gz; \
+ curl -fsSL "https://github.com/just-containers/s6-overlay/releases/download/${S6_OVERLAY_V}/s6-overlay-${S}.tar.xz" -o /tmp/s6_arch.tar.xz; \
+ curl -fsSL "https://github.com/just-containers/s6-overlay/releases/download/${S6_OVERLAY_V}/s6-overlay-noarch.tar.xz" -o /tmp/s6_noarch.tar.xz && ls -l /tmp
+
+#安装面板文件
+RUN set -eux; \
+ mkdir -p /etc/ShellCrash/ruleset /etc/ShellCrash/ui; \
+ curl -fsSL "https://github.com/juewuy/ShellCrash/raw/update/bin/geodata/mrs.tar.gz" | tar -zxf - -C /etc/ShellCrash/ruleset; \
+ curl -fsSL "https://github.com/juewuy/ShellCrash/raw/update/bin/dashboard/zashboard.tar.gz" | tar -zxf - -C /etc/ShellCrash/ui
+
+############################
+# Stage 2: runtime
+############################
+FROM alpine:latest
+
+ARG TZ=Asia/Shanghai
+
+LABEL org.opencontainers.image.source="https://github.com/juewuy/ShellCrash"
+#安装依赖
+RUN apk add --no-cache \
+ wget \
+ ca-certificates \
+ tzdata \
+ nftables \
+ iproute2 \
+ dcron
+
+RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
+ echo "${TZ}" > /etc/timezone
+
+#复制文件
+COPY --from=builder /etc/ShellCrash /etc/ShellCrash
+COPY --from=builder /tmp/CrashCore.tar.gz /etc/ShellCrash/CrashCore.tar.gz
+COPY --from=builder /etc/profile /etc/profile
+COPY --from=builder /usr/bin/crash /usr/bin/crash
+
+#安装s6
+COPY --from=builder /tmp/s6_arch.tar.xz /tmp/s6_arch.tar.xz
+COPY --from=builder /tmp/s6_noarch.tar.xz /tmp/s6_noarch.tar.xz
+RUN tar -xJf /tmp/s6_noarch.tar.xz -C / && rm -rf /tmp/s6_noarch.tar.xz
+RUN tar -xJf /tmp/s6_arch.tar.xz -C / && rm -rf /tmp/s6_arch.tar.xz
+COPY docker/s6-rc.d /etc/s6-overlay/s6-rc.d
+ENV S6_CMD_WAIT_FOR_SERVICES=1
+
+ENTRYPOINT ["/init"]
+
diff --git a/README_CN.md b/README_CN.md
index c2dca640..489887af 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -99,26 +99,20 @@ export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' && wget
export url='http://t.jwsc.eu.org' && wget -q -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && source /etc/profile &> /dev/null
```
-~**虚拟机/Docker环境安装:**
+##### ~**虚拟机安装:**
-虚拟机或Docker环境推荐使用Alpine镜像安装
-
-这里以Docker为例(其他虚拟机请自行查找安装Alpine镜像安装教程)
+虚拟机环境强烈建议使用Alpine镜像安装
```shell
-#注意,以下命令请分步执行!
-#Docker一键启动Alpine镜像
-docker run -d --name ShellCrash alpine sleep infinity
-#进入容器内sh环境
-docker exec -it ShellCrash sh
#安装必要依赖
-apk add curl
-apk add nftables
+apk add --no-cache wget openrc ca-certificates tzdata nftables iproute2 dcron
#执行安装命令
-export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' && sh -c "$(curl -kfsSl $url/install.sh)" && source /etc/profile &> /dev/null
+export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && source /etc/profile &> /dev/null
```
+##### ~Docker安装:
+请前往[ShellCrash官方Docker镜像](https://hub.docker.com/r/juewuy/shellcrash)
### **本地安装:**
@@ -158,4 +152,7 @@ ubus/iproute-doc 极低 缺少时无法正常获取本机host地址
机场推荐:
--
+
+#### [Dler-墙洞,多年稳定运行,功能齐全](https://dler.pro/auth/register?affid=89698)
+
#### [大米-群友力荐,流媒体解锁,月付推荐](https://1s.bigmeok.me/user#/register?code=2PuWY9I7)
diff --git a/ShellCrash.tar.gz b/ShellCrash.tar.gz
index 9c17607e..8b64da87 100644
Binary files a/ShellCrash.tar.gz and b/ShellCrash.tar.gz differ
diff --git a/bin/clashfm.tar.gz b/bin/clashfm.tar.gz
index 9c17607e..8b64da87 100644
Binary files a/bin/clashfm.tar.gz and b/bin/clashfm.tar.gz differ
diff --git a/bin/version b/bin/version
index dfb5ec9e..b7697083 100644
--- a/bin/version
+++ b/bin/version
@@ -1,4 +1,4 @@
meta_v=v1.19.17
singboxr_v=1.13.0-alpha.27
-versionsh=1.9.3beta8
+versionsh=1.9.3beta9
GeoIP_v=20251205
diff --git a/docker/compose.yml b/docker/compose.yml
new file mode 100644
index 00000000..41af2d9d
--- /dev/null
+++ b/docker/compose.yml
@@ -0,0 +1,24 @@
+version: "3.9"
+
+services:
+ shellclash:
+ image: shellclash:latest
+ container_name: shellclash
+ networks:
+ macvlan_lan:
+ ipv4_address: 192.168.31.222
+ cap_add:
+ - SYS_ADMIN
+ - NET_ADMIN
+ - NET_RAW
+ devices:
+ - "/dev/net/tun:/dev/net/tun"
+ sysctls:
+ net.ipv4.ip_forward: 1
+ volumes:
+ - /etc/ShellCrash:/root/ShellCrash
+ restart: unless-stopped
+
+networks:
+ macvlan_lan:
+ external: true
diff --git a/docker/s6-rc.d/afstart/dependencies.d/shellcrash b/docker/s6-rc.d/afstart/dependencies.d/shellcrash
new file mode 100644
index 00000000..e69de29b
diff --git a/docker/s6-rc.d/afstart/type b/docker/s6-rc.d/afstart/type
new file mode 100644
index 00000000..bdd22a18
--- /dev/null
+++ b/docker/s6-rc.d/afstart/type
@@ -0,0 +1 @@
+oneshot
diff --git a/docker/s6-rc.d/afstart/up b/docker/s6-rc.d/afstart/up
new file mode 100644
index 00000000..2d2c62ba
--- /dev/null
+++ b/docker/s6-rc.d/afstart/up
@@ -0,0 +1,2 @@
+#!/command/execlineb -P
+/etc/ShellCrash/start.sh afstart
diff --git a/docker/s6-rc.d/bfstart/type b/docker/s6-rc.d/bfstart/type
new file mode 100644
index 00000000..bdd22a18
--- /dev/null
+++ b/docker/s6-rc.d/bfstart/type
@@ -0,0 +1 @@
+oneshot
diff --git a/docker/s6-rc.d/bfstart/up b/docker/s6-rc.d/bfstart/up
new file mode 100644
index 00000000..a3560bd9
--- /dev/null
+++ b/docker/s6-rc.d/bfstart/up
@@ -0,0 +1,2 @@
+#!/command/execlineb -P
+/etc/ShellCrash/start.sh bfstart
diff --git a/docker/s6-rc.d/crond/run b/docker/s6-rc.d/crond/run
new file mode 100644
index 00000000..9d793843
--- /dev/null
+++ b/docker/s6-rc.d/crond/run
@@ -0,0 +1,3 @@
+#!/command/execlineb -P
+fdmove -c 2 1
+exec crond -f -l 8
\ No newline at end of file
diff --git a/docker/s6-rc.d/crond/type b/docker/s6-rc.d/crond/type
new file mode 100644
index 00000000..5883cff0
--- /dev/null
+++ b/docker/s6-rc.d/crond/type
@@ -0,0 +1 @@
+longrun
diff --git a/docker/s6-rc.d/shellcrash/dependencies.d/bfstart b/docker/s6-rc.d/shellcrash/dependencies.d/bfstart
new file mode 100644
index 00000000..e69de29b
diff --git a/docker/s6-rc.d/shellcrash/run b/docker/s6-rc.d/shellcrash/run
new file mode 100644
index 00000000..b1520b41
--- /dev/null
+++ b/docker/s6-rc.d/shellcrash/run
@@ -0,0 +1,6 @@
+#!/bin/sh
+set -e
+
+. /etc/ShellCrash/configs/command.env
+
+exec /bin/sh -c "${COMMAND} > /dev/null"
diff --git a/docker/s6-rc.d/shellcrash/type b/docker/s6-rc.d/shellcrash/type
new file mode 100644
index 00000000..5883cff0
--- /dev/null
+++ b/docker/s6-rc.d/shellcrash/type
@@ -0,0 +1 @@
+longrun
diff --git a/docker/s6-rc.d/user/contents.d/crond b/docker/s6-rc.d/user/contents.d/crond
new file mode 100644
index 00000000..e69de29b
diff --git a/public/task.list b/public/task.list
index 2a610ee5..f8bbe00c 100644
--- a/public/task.list
+++ b/public/task.list
@@ -1,10 +1,10 @@
#任务ID#任务命令#任务说明(#号隔开,任务命令和说明中都不允许包含#号)
-101#$CRASHDIR/start.sh start#启动clash服务
-102#$CRASHDIR/start.sh stop#停止clash服务
-103#$CRASHDIR/start.sh restart#重启clash服务
-104#$CRASHDIR/start.sh update_config#更新订阅并重启服务
-105#$CRASHDIR/start.sh hotupdate#热更新订阅-不推荐
+101#$CRASHDIR/start.sh start#启动ShellCrash服务
+102#$CRASHDIR/start.sh stop#停止ShellCrash服务
+103#$CRASHDIR/start.sh restart#重启ShellCrash服务
+104#$CRASHDIR/start.sh update_config#更新在线订阅并重启服务
+105#$CRASHDIR/start.sh hotupdate#热更新在线订阅(不重启)
106#$CRASHDIR/start.sh web_save#自动保存面板配置
107#$CRASHDIR/task/task.sh ntp#自动同步ntp时间
diff --git a/scripts/init.sh b/scripts/init.sh
index 4cdb733d..9ae31fc4 100644
--- a/scripts/init.sh
+++ b/scripts/init.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# Copyright (C) Juewuy
-version=1.9.3beta8
+version=1.9.3beta9
setdir() {
dir_avail() {
@@ -153,7 +153,7 @@ setconfig() { #脚本配置工具
#参数1代表变量名,参数2代表变量值,参数3即文件路径
[ -z "$3" ] && configpath="$CRASHDIR"/configs/ShellCrash.cfg || configpath="${3}"
if grep -q "^${1}=" "$configpath"; then
- sed -i "s#${1}=.*#${1}=${2}#g" "$configpath"
+ sed -i "s#^${1}=.*#${1}=${2}#g" "$configpath"
else
printf '%s=%s\n' "$1" "$2" >>"$configpath"
fi
@@ -174,10 +174,11 @@ setconfig() { #脚本配置工具
[ -f "/data/etc/crontabs/root" ] && systype=mi_snapshot #小米设备
[ -w "/var/mnt/cfg/firewall" ] && systype=ng_snapshot #NETGEAR设备
#容器内环境
-grep -qE '/(docker|lxc|kubepods|crio|containerd)/' /proc/1/cgroup || [ -f /run/.containerenv ] || [ -f /.dockerenv ] && systype=container
+grep -qE '/(docker|lxc|kubepods|crio|containerd)/' /proc/1/cgroup || [ -f /run/.containerenv ] || [ -f /.dockerenv ] && systype='container'
#检查环境变量
-[ -z "$CRASHDIR" -a -n "$clashdir" ] && CRASHDIR=$clashdir
-[ -z "$CRASHDIR" -a -d /tmp/SC_tmp ] && setdir
+[ "$systype" = 'container' ] && CRASHDIR='/etc/ShellCrash'
+[ -z "$CRASHDIR" ] && [ -n "$clashdir" ] && CRASHDIR="$clashdir"
+[ -z "$CRASHDIR" ] && [ -d /tmp/SC_tmp ] && setdir
#移动文件
mkdir -p ${CRASHDIR}
mv -f /tmp/SC_tmp/* ${CRASHDIR} 2>/dev/null
@@ -307,12 +308,19 @@ fi
[ "$systype" = 'container' ] && {
setconfig userguide '1'
setconfig crashcore 'meta'
- setconfig redir_mod "混合模式"
setconfig dns_mod 'mix'
setconfig firewall_area '1'
setconfig firewall_mod 'nftables'
- setconfig start_old '已开启'
+ setconfig release_type 'master'
+ setconfig start_old '未开启'
echo "$CRASHDIR/menu.sh" >> /etc/profile
+ cat > /usr/bin/crash <<'EOF'
+#!/bin/sh
+CRASHDIR=${CRASHDIR:-/etc/ShellCrash}
+export CRASHDIR
+exec "$CRASHDIR/menu.sh" "$@"
+EOF
+ chmod 755 /usr/bin/crash
}
setconfig systype $systype
#删除临时文件
diff --git a/scripts/menu.sh b/scripts/menu.sh
index 09b4331d..10a0d634 100644
--- a/scripts/menu.sh
+++ b/scripts/menu.sh
@@ -19,7 +19,7 @@ setconfig() {
#参数1代表变量名,参数2代表变量值,参数3即文件路径
[ -z "$3" ] && configpath="$CRASHDIR"/configs/ShellCrash.cfg || configpath="${3}"
if grep -q "^${1}=" "$configpath"; then
- sed -i "s#${1}=.*#${1}=${2}#g" "$configpath"
+ sed -i "s#^${1}=.*#${1}=${2}#g" "$configpath"
else
printf '%s=%s\n' "$1" "$2" >>"$configpath"
fi
@@ -67,6 +67,8 @@ ckstatus() {
[ -n "$(find /etc/rc.d -name '*shellcrash')" ] && autostart=enable || autostart=disable
elif ckcmd systemctl; then
[ "$(systemctl is-enabled shellcrash.service 2>&1)" = enabled ] && autostart=enable || autostart=disable
+ elif grep -q 's6' /proc/1/comm; then
+ [ -f /etc/s6-overlay/s6-rc.d/user/contents.d/afstart ] && autostart=enable || autostart=disable
elif rc-status -r >/dev/null 2>&1; then
rc-update show default | grep -q "shellcrash" && autostart=enable || autostart=disable
else
@@ -1228,7 +1230,8 @@ setboot() { #启动相关设置
# 禁止自启动:删除各系统的启动项
[ -d /etc/rc.d ] && cd /etc/rc.d && rm -rf *shellcrash >/dev/null 2>&1 && cd - >/dev/null
ckcmd systemctl && systemctl disable shellcrash.service >/dev/null 2>&1
- [rc-status -r >/dev/null 2>&1 && rc-update del shellcrash default >/dev/null
+ grep -q 's6' /proc/1/comm && rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
+ rc-status -r >/dev/null 2>&1 && rc-update del shellcrash default >/dev/null 2>&1
touch ${CRASHDIR}/.dis_startup
autostart=disable
echo -e "\033[33m已禁止ShellCrash开机启动!\033[0m"
@@ -1236,7 +1239,8 @@ setboot() { #启动相关设置
# 允许自启动:配置各系统的启动项
[ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ] && /etc/init.d/shellcrash enable
ckcmd systemctl && systemctl enable shellcrash.service >/dev/null 2>&1
- rc-status -r >/dev/null 2>&1 && rc-update add shellcrash default >/dev/null
+ grep -q 's6' /proc/1/comm && touch /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
+ rc-status -r >/dev/null 2>&1 && rc-update add shellcrash default >/dev/null 2>&1
rm -rf ${CRASHDIR}/.dis_startup
autostart=enable
echo -e "\033[32m已设置ShellCrash开机启动!\033[0m"
@@ -1248,11 +1252,13 @@ setboot() { #启动相关设置
echo -e "\033[33m改为使用保守模式启动服务!!\033[0m"
[ -d /etc/rc.d ] && cd /etc/rc.d && rm -rf *shellcrash >/dev/null 2>&1 && cd - >/dev/null
ckcmd systemctl && systemctl disable shellcrash.service >/dev/null 2>&1
+ grep -q 's6' /proc/1/comm && rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
+ rc-status -r >/dev/null 2>&1 && rc-update del shellcrash default >/dev/null 2>&1
start_old=已开启
setconfig start_old $start_old
${CRASHDIR}/start.sh stop
else
- if grep -qE 'procd|systemd' /proc/1/comm || rc-status -r >/dev/null 2>&1; then
+ if grep -qE 'procd|systemd|s6' /proc/1/comm || rc-status -r >/dev/null 2>&1; then
echo -e "\033[32m改为使用系统守护进程启动服务!!\033[0m"
${CRASHDIR}/start.sh cronset "ShellCrash初始化"
start_old=未开启
@@ -1474,7 +1480,8 @@ set_redir_mod() { #代理模式设置
}
[ -n "$(ls /dev/net/tun 2>/dev/null)" ] || ip tuntap >/dev/null 2>&1 && sup_tun=1
[ -z "$firewall_area" ] && firewall_area=1
- [ -z "$firewall_mod" ] && firewall_mod=未设置
+ [ -z "$redir_mod" ] && [ "$USER" = "root" -o "$USER" = "admin" ] && redir_mod='Redir模式'
+ [ -z "$redir_mod" ] && redir_mod='纯净模式'
firewall_area_dsc=$(echo "仅局域网 仅本机 局域网+本机 纯净模式 主-旁转发($bypass_host)" | cut -d' ' -f$firewall_area)
echo "-----------------------------------------------"
echo -e "当前代理模式为:\033[47;30m$redir_mod\033[0m;ShellCrash核心为:\033[47;30m $crashcore \033[0m"
diff --git a/scripts/shellcrash.openrc b/scripts/shellcrash.openrc
index acd92ba2..a0b21567 100644
--- a/scripts/shellcrash.openrc
+++ b/scripts/shellcrash.openrc
@@ -68,7 +68,6 @@ stop() {
# 清理 firewall、proxy
"$CRASHDIR/start.sh" stop_firewall
- "$CRASHDIR/start.sh" unset_proxy
eend $?
}
diff --git a/scripts/shellcrash.procd b/scripts/shellcrash.procd
index 1227661e..f884dd10 100644
--- a/scripts/shellcrash.procd
+++ b/scripts/shellcrash.procd
@@ -35,5 +35,4 @@ start_service() {
stop_service() {
procd_close_instance
$CRASHDIR/start.sh stop_firewall
- $CRASHDIR/start.sh unset_proxy
}
diff --git a/scripts/shellcrash.service b/scripts/shellcrash.service
index 2b78998b..ac2bc3c0 100644
--- a/scripts/shellcrash.service
+++ b/scripts/shellcrash.service
@@ -10,7 +10,7 @@ StandardOutput=null
ExecStartPre=/etc/ShellCrash/start.sh bfstart
ExecStart=/etc/ShellCrash/CrashCore run -D /etc/ShellCrash -C /tmp/ShellCrash/jsons >/dev/null
ExecStartPost=/etc/ShellCrash/start.sh afstart
-ExecStopPost=/etc/ShellCrash/start.sh stop_firewall ; /etc/ShellCrash/start.sh unset_proxy
+ExecStopPost=/etc/ShellCrash/start.sh stop_firewall
Restart=on-abnormal
RestartSec=10s
LimitNOFILE=infinity
diff --git a/scripts/start.sh b/scripts/start.sh
index aae1a655..537da780 100644
--- a/scripts/start.sh
+++ b/scripts/start.sh
@@ -16,8 +16,8 @@ getconfig() { #读取配置及全局变量
#加载配置文件
. "$CRASHDIR"/configs/ShellCrash.cfg >/dev/null
#缺省值
- [ -z "$redir_mod" ] && [ "$USER" = "root" -o "$USER" = "admin" ] && redir_mod=Redir模式
- [ -z "$redir_mod" ] && redir_mod=纯净模式
+ [ -z "$redir_mod" ] && [ "$USER" = "root" -o "$USER" = "admin" ] && redir_mod='Redir模式'
+ [ -z "$redir_mod" ] && firewall_area='4'
[ -z "$skip_cert" ] && skip_cert=已开启
[ -z "$dns_mod" ] && dns_mod=fake-ip
[ -z "$ipv6_redir" ] && ipv6_redir=未开启
@@ -70,7 +70,7 @@ setconfig() { #脚本配置工具
#参数1代表变量名,参数2代表变量值,参数3即文件路径
[ -z "$3" ] && configpath="$CRASHDIR"/configs/ShellCrash.cfg || configpath="${3}"
if grep -q "^${1}=" "$configpath"; then
- sed -i "s#${1}=.*#${1}=${2}#g" "$configpath"
+ sed -i "s#^${1}=.*#${1}=${2}#g" "$configpath"
else
printf '%s=%s\n' "$1" "$2" >>"$configpath"
fi
@@ -290,15 +290,16 @@ parse_singbox_dns() { #singbox的dns分割工具
echo '"type": "'"$type"'", "server": "'"$server"'", "server_port": '"$port"','
}
urlencode() {
- local i c hex
LC_ALL=C
- for i in $(printf '%s' "$1" | od -An -tx1); do
- case "$i" in
- 2d|2e|5f|7e|3[0-9]|4[1-9A-Fa-f]|5[A-Fa-f]|6[1-9A-Fa-f]|7[0-9A-Ea-e])
- printf "\\$(printf '%03o' "0x$i")"
+ printf '%s' "$1" \
+ | hexdump -v -e '/1 "%02X\n"' \
+ | while read -r hex; do
+ case "$hex" in
+ 2D|2E|5F|7E|3[0-9]|4[1-9A-F]|5[A-F]|6[1-9A-F]|7[0-9A-E])
+ printf "\\$(printf '%03o' "0x$hex")"
;;
*)
- printf '%%%02X' "0x$i"
+ printf "%%%s" "$hex"
;;
esac
done
@@ -389,7 +390,11 @@ get_core_config() { #下载内核配置文件
#如果传来的是Url链接则合成Https链接,否则直接使用Https链接
if [ -z "$Https" ]; then
#Urlencord转码处理保留字符
- urlencodeUrl="exclude=$(urlencode "$exclude")&include=$(urlencode "$include")&url=$(urlencode "$Url")&config=$(urlencode "$Config")"
+ if ckcmd hexdump;then
+ urlencodeUrl="exclude=$(urlencode "$exclude")&include=$(urlencode "$include")&url=$(urlencode "$Url")&config=$(urlencode "$Config")"
+ else
+ urlencodeUrl="exclude=$exclude&include=$include&url=$Url&config=$Config"
+ fi
Https="${Server}/sub?target=${target}&${Server_ua}=${user_agent}&insert=true&new_name=true&scv=true&udp=true&${urlencodeUrl}"
url_type=true
fi
@@ -402,7 +407,7 @@ get_core_config() { #下载内核配置文件
core_config_new="$TMPDIR"/${target}_config.${format}
rm -rf ${core_config_new}
$0 webget "$core_config_new" "$Https" echoon rediron skipceron "$user_agent"
- if [ "$?" = "1" ]; then
+ if [ "$?" != "0" ]; then
if [ -z "$url_type" ]; then
echo "-----------------------------------------------"
logger "配置文件获取失败!" 31
@@ -410,7 +415,7 @@ get_core_config() { #下载内核配置文件
echo "-----------------------------------------------"
exit 1
else
- if [ "$retry" -ge 3 ]; then
+ if [ -n "$retry" ] && [ "$retry" -ge 3 ]; then
logger "无法获取配置文件,请检查链接格式以及网络连接状态!" 31
echo -e "\033[32m也可用浏览器下载以上链接后,使用WinSCP手动上传到/tmp目录后执行crash命令本地导入!\033[0m"
exit 1
@@ -565,10 +570,10 @@ EOF
sed -i "/#自定义策略组/d" "$TMPDIR"/proxy-groups.yaml
[ -n "$(grep -Ev '^#' "$CRASHDIR"/yamls/proxy-groups.yaml 2>/dev/null)" ] && {
#获取空格数
- space_name=$(grep -aE '^ *- name: ' "$TMPDIR"/proxy-groups.yaml | head -n 1 | grep -oE '^ *')
- space_proxy=$(grep -A 1 'proxies:$' "$TMPDIR"/proxy-groups.yaml | grep -aE '^ *- ' | head -n 1 | grep -oE '^ *')
+ space_name=$(grep -aE '^ *- \{?name: ' "$TMPDIR"/proxy-groups.yaml | head -n 1 | grep -oE '^ *')
+ space_proxy="$space_name "
#合并自定义策略组到proxy-groups.yaml
- cat "$CRASHDIR"/yamls/proxy-groups.yaml | sed "/^#/d" | sed "s/#.*//g" | sed '1i\ #自定义策略组开始' | sed '$a\ #自定义策略组结束' | sed "s/^ */${space_name} /g" | sed "s/^ *- /${space_proxy}- /g" | sed "s/^ *- name: /${space_name}- name: /g" >"$TMPDIR"/proxy-groups_add.yaml
+ cat "$CRASHDIR"/yamls/proxy-groups.yaml | sed "/^#/d" | sed "s/#.*//g" | sed '1i\ #自定义策略组开始' | sed '$a\ #自定义策略组结束' | sed "s/^ */${space_name} /g" | sed "s/^ *- /${space_proxy}- /g" | sed "s/^ *- name: /${space_name}- name: /g" | sed "s/^ *- {name: /${space_name}- {name: /g" >"$TMPDIR"/proxy-groups_add.yaml
cat "$TMPDIR"/proxy-groups.yaml >>"$TMPDIR"/proxy-groups_add.yaml
mv -f "$TMPDIR"/proxy-groups_add.yaml "$TMPDIR"/proxy-groups.yaml
oldIFS="$IFS"
@@ -1463,10 +1468,10 @@ start_nft_wan() { #nftables公网防火墙
}
start_nftables() { #nftables配置总入口
#初始化nftables
- nft add table inet shellcrash
- nft flush table inet shellcrash
+ nft add table inet shellcrash 2>/dev/null
+ nft flush table inet shellcrash 2>/dev/null
#公网访问防火墙
- start_nft_wan
+ [ "$systype" != 'container' ] && start_nft_wan
#启动DNS劫持
[ "$dns_no" != "已禁用" -a "$dns_redir" != "已开启" -a "$firewall_area" -le 3 ] && {
[ "$lan_proxy" = true ] && start_nft_dns prerouting prerouting #局域网dns转发
@@ -1706,7 +1711,7 @@ stop_firewall() { #还原防火墙配置
#还原防火墙文件
[ -s /etc/init.d/firewall.bak ] && mv -f /etc/init.d/firewall.bak /etc/init.d/firewall
#others
- sed -i '/shellcrash-dns-repair/d' /etc/resolv.conf
+ [ "$systype" != 'container' ] && sed -i '/shellcrash-dns-repair/d' /etc/resolv.conf >/dev/null 2>&1
}
#启动相关
web_save() { #最小化保存面板节点选择
@@ -2045,20 +2050,6 @@ hotupdate() { #热更新订阅
put_save http://127.0.0.1:${db_port}/configs "{\"path\":\""$CRASHDIR"/config.$format\"}"
rm -rf "$TMPDIR"/CrashCore
}
-set_proxy() { #设置环境变量
- if [ "$local_type" = "环境变量" ]; then
- [ -w ~/.bashrc ] && profile=~/.bashrc
- [ -w /etc/profile ] && profile=/etc/profile
- echo 'export all_proxy=http://127.0.0.1:'"$mix_port" >>$profile
- echo 'export ALL_PROXY=$all_proxy' >>$profile
- fi
-}
-unset_proxy() { #卸载环境变量
- [ -w ~/.bashrc ] && profile=~/.bashrc
- [ -w /etc/profile ] && profile=/etc/profile
- sed -i '/all_proxy/'d $profile
- sed -i '/ALL_PROXY/'d $profile
-}
getconfig #读取配置及全局变量
@@ -2068,7 +2059,7 @@ start)
[ -n "$(pidof CrashCore)" ] && $0 stop #禁止多实例
stop_firewall #清理路由策略
#使用不同方式启动服务
- if [ "$firewall_area" = "5" ]; then #主旁转发
+ if [ "$firewall_area" = "5" ]; then #主旁转发
start_firewall
elif [ "$start_old" = "已开启" ]; then
bfstart && start_old
@@ -2081,15 +2072,14 @@ start)
systemctl daemon-reload
systemctl start shellcrash.service || start_error
}
+ elif grep -q 's6' /proc/1/comm; then
+ bfstart && /command/s6-svc -u /run/service/shellcrash && afstart &
elif rc-status -r >/dev/null 2>&1; then
rc-service shellcrash stop >/dev/null 2>&1
rc-service shellcrash start
else
bfstart && start_old
fi
- if [ "$2" = "infinity" ]; then #增加容器自启方式,请将CMD设置为"$CRASHDIR"/start.sh start infinity
- sleep infinity
- fi
;;
stop)
logger ShellCrash服务即将关闭……
@@ -2104,11 +2094,13 @@ stop)
systemctl stop shellcrash.service >/dev/null 2>&1
elif [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ]; then
/etc/init.d/shellcrash stop >/dev/null 2>&1
+ elif grep -q 's6' /proc/1/comm; then
+ /command/s6-svc -d /run/service/shellcrash
+ stop_firewall
elif rc-status -r >/dev/null 2>&1; then
rc-service shellcrash stop >/dev/null 2>&1
else
stop_firewall #清理路由策略
- unset_proxy #禁用本机代理
fi
PID=$(pidof CrashCore) && [ -n "$PID" ] && kill -9 $PID >/dev/null 2>&1
#清理缓存目录
@@ -2171,48 +2163,51 @@ init)
;;
webget)
#设置临时代理
- if [ -n "$(pidof CrashCore)" ]; then
- [ -n "$authentication" ] && auth="$authentication@"
+ if pidof CrashCore >/dev/null; then
+ [ -n "$authentication" ] && auth="$authentication@" || auth=""
export all_proxy="http://${auth}127.0.0.1:$mix_port"
- url=$(echo $3 | sed 's#https://.*jsdelivr.net/gh/juewuy/ShellCrash[@|/]#https://raw.githubusercontent.com/juewuy/ShellCrash/#' | sed 's#https://gh.jwsc.eu.org/#https://raw.githubusercontent.com/juewuy/ShellCrash/#')
- else
- url=$(echo $3 | sed 's#https://raw.githubusercontent.com/juewuy/ShellCrash/#https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@#')
- fi
+ url=$(printf '%s\n' "$3" |
+ sed -e 's#https://.*jsdelivr.net/gh/juewuy/ShellCrash[@|/]#https://raw.githubusercontent.com/juewuy/ShellCrash/#' \
+ -e 's#https://gh.jwsc.eu.org/#https://raw.githubusercontent.com/juewuy/ShellCrash/#')
+ else
+ url=$(printf '%s\n' "$3" |
+ sed 's#https://raw.githubusercontent.com/juewuy/ShellCrash/#https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@#')
+ fi
#参数【$2】代表下载目录,【$3】代表在线地址
#参数【$4】代表输出显示,【$5】不启用重定向
#参数【$6】代表验证证书,【$7】使用自定义UA
[ -n "$7" ] && agent="--user-agent \"$7\""
- if curl --version >/dev/null 2>&1; then
+ if wget --version >/dev/null 2>&1; then
+ [ "$4" = "echooff" ] && progress='-q' || progress='-q --show-progress'
+ [ "$5" = "rediroff" ] && redirect='--max-redirect=0' || redirect=''
+ [ "$6" = "skipceroff" ] && certificate='' || certificate='--no-check-certificate'
+ wget -Y on $agent $progress $redirect $certificate --timeout=3 -O "$2" "$url" && exit 0 #成功则退出否则重试
+ wget -Y off $agent $progress $redirect $certificate --timeout=5 -O "$2" "$3"
+ exit $?
+ elif curl --version >/dev/null 2>&1; then
[ "$4" = "echooff" ] && progress='-s' || progress='-#'
[ "$5" = "rediroff" ] && redirect='' || redirect='-L'
[ "$6" = "skipceroff" ] && certificate='' || certificate='-k'
- [ -n "$7" ] && agent="--user-agent \"$7\""
if curl --version | grep -q '^curl 8.' && ckcmd base64; then
- auth_b64=$(echo -n "$authentication" | base64)
- result=$(curl $agent -w %{http_code} --connect-timeout 3 --proxy-header "Proxy-Authorization: Basic $auth_b64" $progress $redirect $certificate -o "$2" "$url")
+ auth_b64=$(printf '%s' "$authentication" | base64)
+ result=$(curl $agent -w '%{http_code}' --connect-timeout 3 --proxy-header "Proxy-Authorization: Basic $auth_b64" $progress $redirect $certificate -o "$2" "$url")
else
- result=$(curl $agent -w %{http_code} --connect-timeout 3 $progress $redirect $certificate -o "$2" "$url")
+ result=$(curl $agent -w '%{http_code}' --connect-timeout 3 $progress $redirect $certificate -o "$2" "$url")
fi
- [ "$result" != "200" ] && export all_proxy="" && result=$(curl $agent -w %{http_code} --connect-timeout 5 $progress $redirect $certificate -o "$2" "$3")
- else
- if wget --version >/dev/null 2>&1; then
- [ "$4" = "echooff" ] && progress='-q' || progress='-q --show-progress'
- [ "$5" = "rediroff" ] && redirect='--max-redirect=0' || redirect=''
- [ "$6" = "skipceroff" ] && certificate='' || certificate='--no-check-certificate'
- [ -n "$7" ] && agent="--user-agent=\"$7\""
- timeout='--timeout=5'
- fi
- [ "$4" = "echoon" ] && progress=''
+ [ "$result" = "200" ] && exit 0 #成功则退出否则重试
+ export all_proxy=""
+ result=$(curl $agent -w '%{http_code}' --connect-timeout 5 $progress $redirect $certificate -o "$2" "$3")
+ [ "$result" = "200" ]
+ exit $?
+ elif ckcmd wget;then
[ "$4" = "echooff" ] && progress='-q'
- wget -Y on $agent $progress $redirect $certificate $timeout -O "$2" "$url"
- if [ "$?" != "0" ]; then
- wget -Y off $agent $progress $redirect $certificate $timeout -O "$2" "$3"
- [ "$?" = "0" ] && result="200"
- else
- result="200"
- fi
+ wget -Y on $progress -O "$2" "$url" && exit 0 #成功则退出否则重试
+ wget -Y off $progress -O "$2" "$3"
+ exit $?
+ else
+ echo "找不到可用下载工具!!!请安装Curl或Wget!!!"
+ exit 1
fi
- [ "$result" = "200" ] && exit 0 || exit 1
;;
*)
"$1" "$2" "$3" "$4" "$5" "$6" "$7"
diff --git a/version b/version
index 5620eef7..c0e9334b 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.9.3beta8
+1.9.3beta9