commit 533bacc
merc
·
2026-07-31 20:06:37 +0000 UTC
parent 533bacc
init
A
Makefile
+17,
-0
1@@ -0,0 +1,17 @@
2+PREFIX ?= /usr/local
3+BINDIR ?= $(PREFIX)/bin
4+MANDIR ?= $(PREFIX)/share/man/man1
5+
6+all:
7+
8+install:
9+ mkdir -p $(DESTDIR)$(BINDIR)
10+ mkdir -p $(DESTDIR)$(MANDIR)
11+ install -m 755 bs $(DESTDIR)$(BINDIR)/bs
12+ install -m 644 bs.1 $(DESTDIR)$(MANDIR)/bs.1
13+
14+uninstall:
15+ rm -f $(DESTDIR)$(BINDIR)/bs
16+ rm -f $(DESTDIR)$(MANDIR)/bs.1
17+
18+.PHONY: all install uninstall
+1,
-0
1@@ -0,0 +1 @@
2+`man bs`
A
bs
+88,
-0
1@@ -0,0 +1,88 @@
2+#!/bin/sh
3+
4+serviceNm="sing-box"
5+
6+m=0
7+for f in /etc/sing-box/list/*.json; do
8+ [ -f "$f" ] || continue
9+ n=$(basename "$f" .json)
10+ [ ${#n} -gt $m ] && m=${#n}
11+done
12+
13+case "$1" in
14+ -L|--list)
15+ i=1
16+ for f in /etc/sing-box/list/*.json; do
17+ [ -f "$f" ] || continue
18+ n=$(basename "$f" .json)
19+ p=$(jq -r '.outbounds[] | select(.type != "direct") | .type' "$f")
20+ [ -z "$p" ] && p="unknown"
21+ printf "%-*s [%d] [%s]\n" "$m" "$n" "$i" "$p"
22+ i=$((i + 1))
23+ done
24+ ;;
25+ -C|--current)
26+ if [ -L /etc/sing-box/active.json ] && [ -e /etc/sing-box/active.json ]; then
27+ l=$(readlink /etc/sing-box/active.json)
28+ n=$(basename "$l" .json)
29+ p=$(jq -r '.outbounds[] | select(.type != "direct") | .type' "$l")
30+ [ -z "$p" ] && p="unknown"
31+ i=1
32+ for f in /etc/sing-box/list/*.json; do
33+ if [ -f "$f" ] && [ "$(basename "$f" .json)" = "$n" ]; then
34+ printf "%-*s [%d] [%s]\n" "$m" "$n" "$i" "$p"
35+ break
36+ fi
37+ i=$((i + 1))
38+ done
39+ else
40+ echo "no active config"
41+ fi
42+ ;;
43+ -S|--stop)
44+ if [ "$(id -u)" -ne 0 ]; then
45+ echo "run as root"
46+ exit 1
47+ fi
48+ rc-service "$serviceNm" stop
49+ rm -f /etc/sing-box/active.json
50+ ;;
51+ -*)
52+ echo "invalid option $1"
53+ exit 1
54+ ;;
55+ *)
56+ if [ -z "$1" ]; then
57+ echo "rtfm"
58+ echo "> man bs"
59+ exit 1
60+ fi
61+
62+ if [ "$1" -eq "$1" ] 2>/dev/null; then
63+ if [ "$(id -u)" -ne 0 ]; then
64+ echo "run as root"
65+ exit 1
66+ fi
67+ i=1
68+ for f in /etc/sing-box/list/*.json; do
69+ [ -f "$f" ] || continue
70+ if [ "$i" -eq "$1" ]; then
71+ ln -sf "/etc/sing-box/list/$(basename "$f")" /etc/sing-box/active.json
72+ rc-service "$serviceNm" restart
73+ exit 0
74+ fi
75+ i=$((i + 1))
76+ done
77+ echo "index $1 not found"
78+ exit 1
79+ fi
80+
81+ if [ ! -f "/etc/sing-box/list/$1.json" ]; then
82+ echo "config $1 not found"
83+ exit 1
84+ fi
85+
86+ ln -sf "/etc/sing-box/list/$1.json" /etc/sing-box/active.json
87+ rc-service "$serviceNm" restart
88+ ;;
89+esac
A
bs.1
+38,
-0
1@@ -0,0 +1,38 @@
2+.Dd $Mdocdate$
3+.Dt BS 1
4+.Os
5+.Sh NAME
6+.Nm bs
7+.Nd a shell script for controlling the
8+.Em 'sing-box'
9+service
10+.Sh SYNOPSIS
11+.Bl -tag -width Ds
12+.It Fl L , Fl -list
13+list available configs
14+.It Fl C , Fl -current
15+show the currently used config
16+.It Fl S , Fl -stop
17+stop the sing-box service and clean up
18+.El
19+.Sh DESCRIPTION
20+.Nm
21+switches between .json configs from
22+.Pa /etc/sing-box/list/
23+.Pp
24+the selected config is symlinked to
25+.Pa /etc/sing-box/active.json
26+.Pp
27+the
28+.Em sing-box-openrc
29+package on Alpine should provide the required service. if not, write your own.
30+.Pp
31+this was written for
32+.Em OpenRC ,
33+so no other init systems are supported. you're free to change this script locally as you wish.
34+.Sh SEE ALSO
35+.Xr rc-service 8 ,
36+.Xr ln 1 ,
37+.Lk https://sing-box.sagernet.org/configuration/ "creating a config"
38+.Sh AUTHORS
39+.An merc <merc@4plt.ch>