aaden-cli 1.6.109-rc.0 → 1.6.110

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,21 @@
1
1
  #!/bin/bash
2
+ # 和 aaden-cli 其他地方一样用 -S 喂密码:aaden 没有免密 sudo、又没有终端时(被装机脚本或 set-device-id 调用)裸 sudo 会直接失败
3
+ sudoS() { echo "Innerken322." | sudo -S -p '' "$@"; }
2
4
 
3
- sudo npm config set prefix /usr/local
5
+ sudoS npm config set prefix /usr/local
4
6
  cd || exit
5
- sudo rm -rf ngrok
7
+ sudoS rm -rf ngrok
6
8
  axel -n 8 "https://aaden-storage.s3.eu-central-1.amazonaws.com/ngrok"
7
- sudo cp -f ngrok /etc/aaden/ngrok
8
- sudo chmod +x /etc/aaden/ngrok
9
+ sudoS cp -f ngrok /etc/aaden/ngrok
10
+ sudoS chmod +x /etc/aaden/ngrok
9
11
 
10
12
  DeviceId=$(cat /var/www/html/Resource/config/config.ini | grep -e DeviceId | cut -d = -f 2 | grep '[1-9]*' | sed 's/"//g')
11
13
  aaden-cli update-ngrok-config $DeviceId
12
14
 
13
15
  ServiceFileName=/etc/systemd/system/aaden-ngrok-v3.service
14
16
 
15
- sudo touch $ServiceFileName
16
- sudo chmod 777 $ServiceFileName
17
+ sudoS touch $ServiceFileName
18
+ sudoS chmod 777 $ServiceFileName
17
19
  echo -e "
18
20
  [Unit]
19
21
  Description=Ngrok Service v3 For Aaden
@@ -29,24 +31,24 @@ ExecStart=/etc/aaden/ngrok -config=/etc/aaden/ngrok-config.yml start-all --log=/
29
31
  [Install]
30
32
  WantedBy=multi-user.target
31
33
  " >$ServiceFileName
32
- sudo rm /etc/systemd/system/aaden-ngrok.service
33
- sudo rm /etc/systemd/system/aaden-ngrok-2.service
34
+ sudoS rm /etc/systemd/system/aaden-ngrok.service
35
+ sudoS rm /etc/systemd/system/aaden-ngrok-2.service
34
36
 
35
- sudo systemctl daemon-reload
36
- sudo systemctl start aaden-ngrok-v3.service
37
- sudo systemctl enable aaden-ngrok-v3.service
38
- sudo systemctl stop aaden-ngrok.service
39
- sudo systemctl stop aaden-ngrok-2.service
40
- sudo systemctl disable aaden-ngrok.service
41
- sudo systemctl disable aaden-ngrok-2.service
37
+ sudoS systemctl daemon-reload
38
+ sudoS systemctl start aaden-ngrok-v3.service
39
+ sudoS systemctl enable aaden-ngrok-v3.service
40
+ sudoS systemctl stop aaden-ngrok.service
41
+ sudoS systemctl stop aaden-ngrok-2.service
42
+ sudoS systemctl disable aaden-ngrok.service
43
+ sudoS systemctl disable aaden-ngrok-2.service
42
44
 
43
- sudo service aaden-ngrok-v3 restart
45
+ sudoS service aaden-ngrok-v3 restart
44
46
 
45
47
 
46
48
 
47
49
  ServiceFileName=/etc/avahi/services/aaden.service
48
- sudo touch $ServiceFileName
49
- sudo chmod 777 $ServiceFileName
50
+ sudoS touch $ServiceFileName
51
+ sudoS chmod 777 $ServiceFileName
50
52
  echo -e "
51
53
  <?xml version="1.0" standalone='no'?><!--*-nxml-*-->
52
54
  <!DOCTYPE service-group SYSTEM "avahi-service.dtd">
@@ -59,7 +61,7 @@ echo -e "
59
61
  </service-group>
60
62
  " >$ServiceFileName
61
63
 
62
- sudo service avahi-daemon restart
64
+ sudoS service avahi-daemon restart
63
65
 
64
66
  echo "ngrok 修复脚本执行完毕。请直接检查ngrok是否正常开启。如果开启,请无视这里的任何报错。"
65
67
 
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ # 和 aaden-cli 其他地方一样用 -S 喂密码:aaden 没有免密 sudo、又没有终端时(被装机脚本或 set-device-id 调用)裸 sudo 会直接失败
3
+ sudoS() { echo "Innerken322." | sudo -S -p '' "$@"; }
2
4
  echo 'Cronjob Before Aaden'
3
5
  echo "Innerken322." | sudo -S crontab -l -u aaden
4
6
  echo 'Cronjob Before Root'
@@ -15,11 +17,10 @@ echo "* * * * * curl --location --request GET 'http://localhost/PHP/BackendData.
15
17
  echo "* * * * * curl --location --request GET 'http://localhost/PHP/BackendData.php?op=autoSendMonthSummary'" >>conf
16
18
  echo "* * * * * curl --location --request GET 'http://localhost/PHP/ZBon.php?op=autoAddCombinedRecord'" >>conf
17
19
  echo "3 * * * * curl --location --request GET 'http://localhost/PHP/writeDETax2024.php'" >>conf
18
- echo "59 4 * * * curl --location -X POST 'http://localhost/PHP/UpdateSelf.php?op=doUpdate'" >>conf
19
- echo "@reboot sleep 60 && curl --location -X POST 'http://localhost/PHP/UpdateSelf.php?op=doUpdate'" >>conf
20
+ # 不再写 git doUpdate(59 4 / @reboot):git 通道 2026-08 已停用,后端 doUpdate 直接跳过,后端更新改走 root 的 auto-upgrade → light-update
20
21
  echo "*/5 * * * * /usr/local/bin/aaden-cli do-log" >>conf
21
- sudo crontab -u aaden -r
22
- sudo crontab -u aaden conf
22
+ sudoS crontab -u aaden -r
23
+ sudoS crontab -u aaden conf
23
24
  echo "Innerken322." | sudo -S rm -f conf
24
25
  crontab -l -u aaden
25
26
  echo "END Aaden Deploy CONFIG"
@@ -1,180 +1,234 @@
1
- echoWithWait() {
1
+ #!/bin/bash
2
+ # Aaden 收银机装机:全新的 Ubuntu(或 WSL)→ 可以交付的收银机。
3
+ # aaden-cli install <设备号> (或在 AadenDeploy 目录下 ./aadensetup.sh <设备号>)
4
+ #
5
+ # - 设备号最先问并查云端(checkDeviceId.sh),撞号在装任何东西之前拦下来
6
+ # - 每一步记下退出码和耗时;关键步骤失败就停下;最后做一遍自检,连同每一步的结果作为「出厂安装」事件上报云端
7
+ # - 全部输出另存一份到 /var/log/aaden-setup.log
8
+ # - 可以重跑:数据库已经初始化过就跳过,配置、主机名、/etc/hosts、定时任务都是覆盖写,不会重复追加
9
+ export PATH="/usr/local/bin:$PATH"
10
+ DIR="$(cd "$(dirname "$0")" && pwd)"
11
+ PW='Innerken322.'
12
+ LOG=/var/log/aaden-setup.log
13
+ WEB=/var/www/html
14
+ BACKEND_SRC=/etc/aaden/updateFiles/backendFiles
15
+
16
+ # 和 aaden-cli 其他地方一样用 -S 从 stdin 喂密码。不能再往 sudoS 的命令里重定向 stdin(密码会被当成内容),
17
+ # 需要重定向时写成 sudoS sh -c '… < 文件'
18
+ sudoS() { echo "$PW" | sudo -S -p '' "$@"; }
19
+ is_wsl() { grep -qi microsoft /proc/version 2>/dev/null; }
20
+
21
+ banner() {
22
+ echo ""
2
23
  echo "#######################################################################"
3
- echo $1 '....'
24
+ echo "# $*"
4
25
  echo "#######################################################################"
5
26
  }
6
27
 
7
- echo ""
8
- echo "#######################################################################"
9
- echo "# Start to configurate aaden! #"
10
- echo "# V 1.0.0 #"
11
- echo "#######################################################################"
12
- echo ""
13
- sudo add-apt-repository ppa:ondrej/php -y
28
+ banner "Aaden 收银机装机"
14
29
 
15
-
16
- echoWithWait "updating System...."
17
- sudo apt-get update -y
18
- sudo apt-get -o Dpkg::Options::='--force-confdef' --force-yes -fuy dist-upgrade
19
-
20
-
21
- echoWithWait "Installing Lamp...."
22
- sudo snap install axel
23
-
24
- sudo apt install apache2 -y
25
- sudo apt install net-tools -y
26
- sudo apt install software-properties-common apt-transport-https -y
27
- echoWithWait "Install PHP7.4"
28
-
29
- sudo apt install mysql-server -y
30
- sudo apt install aptitude -y
31
- sudo apt install curl -y
32
- sudo aptitude -y install expect
33
- sudo apt install default-jdk -y
34
- sudo apt install php7.4 php7.4-common libapache2-mod-php7.4 php7.4-cli -y
35
- sudo apt install php7.4-xml -y
36
- sudo apt install php7.4-curl php7.4-mysql php7.4-gd php7.4-zip php7.4-intl php7.4-common php7.4-mbstring -y
37
- sudo update-alternatives --set php /usr/bin/php7.4
38
- sudo update-alternatives --set phar /usr/bin/phar7.4
39
- sudo update-alternatives --set phar.phar /usr/bin/phar.phar7.4
40
-
41
- sudo systemctl restart apache2
42
-
43
- echoWithWait "Install Complate"
44
-
45
-
46
- sudo apt -y install vim apt-transport-https wget software-properties-common
47
-
48
-
49
- echoWithWait "Install Docker Requirment"
50
- sudo apt-get install -y \
51
- apt-transport-https \
52
- ca-certificates \
53
- curl \
54
- gnupg-agent \
55
- software-properties-common
56
-
57
- sudo apt update -y
58
- sudo apt-get install ttyload -y
59
-
60
- echoWithWait "Deploying ssh"
61
-
62
- sudo apt-get install openssh-server -y
63
-
64
- echoWithWait "Installing Pip for python3"
65
- sudo apt-get install python3-pip -y
66
-
67
- echoWithWait "Get Requests library for python3"
68
- python3 -m pip install requests
69
-
70
- sudo apt-get install unzip -y
71
- curl -sS https://getcomposer.org/installer -o composer-setup.php
72
- sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer
73
- sudo composer self-update
74
- composer -v
75
-
76
- sudo chmod +x files/getFile.sh
77
- sudo chmod 777 -R .
78
-
79
- cd files/ || exit
80
- ./getFile.sh
81
- cd ..
82
-
83
- echoWithWait "Configing MYSQL SECURE, only for remote root disable no, else follow it and set to yes, please set the root password as defaultPassword"
84
-
85
- sudo chmod +x scureSql.sh
86
- sudo /bin/bash scureSql.sh 'Innerken322.'
87
-
88
- echoWithWait "Configing Mysql"
89
- cd /etc/aaden/updateFiles || exit
90
-
91
- sudo mysql -uroot < backendFiles/new.sql
92
-
93
- echoWithWait "Uploading PHP Files"
94
- sudo mv backendFiles/* /var/www/html/
95
- sudo service apache2 restart
96
- sudo chown -hR www-data:www-data /var/www/html
97
-
98
- sudo chmod -R 777 /var/www/html/Resource
99
- sudo chmod +x /var/www/html/crontab.sh
100
-
101
- # give excute permission to migrations
102
- sudo chmod +x /var/www/html/PHP/vendor/bin/phinx
103
- sudo chmod +x /var/www/html/PHP/vendor/robmorgan/phinx/bin/phinx
104
-
105
-
106
- echoWithWait "Skip App Install"
107
-
108
-
109
-
110
-
111
- echoWithWait "Add Cronjob"
112
- sudo touch conf
113
- sudo chmod 777 conf
114
- echo "* * * * * wget -O /dev/null http://localhost/PHP/AccessLog.php?op=reportStatus" >>conf
115
- echo "* * * * * /var/www/html/crontab.sh > /dev/null" >>conf
116
- crontab conf && sudo rm -f conf
117
- crontab -l
118
-
119
- echoWithWait "Finishing Install"
120
-
121
- if [ -z "$1" ]; then
122
- read -p 'DeviceId: ' DeviceId
123
- else
124
- DeviceId=$1
30
+ # ---------------------------------------------------------------- 设备号(最先问,先查撞号)
31
+ DEVICE_ID="$1"
32
+ if [ -z "$DEVICE_ID" ]; then
33
+ read -r -p '设备号: ' DEVICE_ID
125
34
  fi
35
+ bash "$DIR/checkDeviceId.sh" "$DEVICE_ID" || exit 1
36
+ DEVICE_ID=$((10#$DEVICE_ID))
37
+ export AADEN_SKIP_DEVICE_CHECK=1 # 后面 set-device-id 不再问第二遍
38
+
39
+ # sudo 凭据先缓存上并一直续着:装机要十几分钟,中途调的 aaden-cli 子命令里还有裸 sudo
40
+ sudoS -v 2>/dev/null || sudo -v || exit 1
41
+ (while kill -0 $$ 2>/dev/null; do sudoS -v 2>/dev/null; sleep 50; done) &
42
+ KEEPALIVE=$!
43
+ trap 'kill $KEEPALIVE 2>/dev/null' EXIT
44
+
45
+ sudoS touch "$LOG" && sudoS chmod 666 "$LOG"
46
+ exec > >(tee -a "$LOG") 2>&1
47
+ echo "$(date '+%F %T') 开始装机,设备号 $DEVICE_ID"
48
+
49
+ # ---------------------------------------------------------------- 步骤记录与上报
50
+ STEPS=""
51
+ step() { # step <名字> <命令…>:输出照常打到屏幕,记下退出码和耗时
52
+ local name=$1 start=$SECONDS code
53
+ shift
54
+ banner "$name"
55
+ "$@"
56
+ code=$?
57
+ STEPS="$STEPS $name=$code/$((SECONDS - start))s"
58
+ [ "$code" = 0 ] || echo "✗ $name 失败(退出码 $code),详细输出见 $LOG"
59
+ return "$code"
60
+ }
126
61
 
127
- echoWithWait "useDeviceId:$DeviceId"
128
-
129
- wget "http://innerken.com/iplogger/index.php?op=register&deviceId=$DeviceId"
130
- wget http://localhost/PHP/AutoSetup.php?DeviceId=$DeviceId
131
- wget http://localhost/PHP/AccessLog.php?op=reportStatus
132
- sudo hostnamectl set-hostname aaden$DeviceId
133
- echo $(hostname -I | cut -d\ -f1) $(hostname) | sudo tee -a /etc/hosts
134
-
135
- echoWithWait "SetUpOfflineUsbDriver"
136
-
137
- sudo usermod -a -G lp aaden
138
- sudo usermod -a -G lp www-data
139
- sudo usermod -a -G root aaden
140
- sudo usermod -a -G root www-data
141
- sudo usermod -a -G adm aaden
142
- sudo usermod -a -G sudo aaden
143
-
144
- echoWithWait "RUN MIGRATION"
145
- # run migrations
146
- cd /var/www/html/PHP || exit
147
- vendor/bin/phinx migrate
62
+ report() { # report <result> <附加内容>:「出厂安装」事件,在云端设备事件里能看到每一步和自检结果
63
+ local content="出厂安装 [${STEPS# }]$2 result:$1"
64
+ python3 - "$DEVICE_ID" "$content" "$(aaden-cli --version 2>/dev/null | tail -n 1)" <<'PY' || echo "(上报云端失败)"
65
+ import json, sys, urllib.request
66
+ device_id, content, version = sys.argv[1:4]
67
+ body = json.dumps({"deviceId": device_id, "content": content, "type": "系统生成", "operator": "aaden-cli v" + version}).encode()
68
+ urllib.request.urlopen(urllib.request.Request("https://cloud-v2.aaden.io/deviceLog/createEvent", body, {"Content-Type": "application/json"}), timeout=10)
69
+ PY
70
+ }
148
71
 
149
- aaden-cli patch
150
- # 日结物化守护进程:每日数据库备份和 DSFinV-K 日结物化都靠它(以前漏在装机脚本外,靠手动补)
151
- aaden-cli auto-write-gdpdu
152
- aaden-cli fix-cronjob
153
- aaden-cli upgrade
154
- aaden-cli update-ngrok-config $DeviceId
155
- aaden-cli fix-ngrok
72
+ must() { # 关键步骤:失败就上报并停下,后面的步骤都依赖它
73
+ step "$@" && return 0
74
+ report 1 " 中止于 $1"
75
+ banner "装机中止:$1 失败。修好之后重新运行同一条命令即可,已经完成的部分会跳过或覆盖。日志:$LOG"
76
+ exit 1
77
+ }
156
78
 
79
+ # ---------------------------------------------------------------- 1. 系统软件
80
+ install_packages() {
81
+ local apt="env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold"
82
+ # 上次装到一半断掉(断电、断网、包脚本失败)留下的半配置状态先收拾掉,否则后面的 apt 全部报错
83
+ sudoS env DEBIAN_FRONTEND=noninteractive dpkg --configure -a
84
+ command -v add-apt-repository >/dev/null || sudoS $apt install software-properties-common || return 1
85
+ # Ubuntu 22.04 起官方源没有 PHP 7.4
86
+ sudoS add-apt-repository -y ppa:ondrej/php || return 1
87
+ sudoS apt-get update || return 1
88
+ sudoS $apt install \
89
+ apache2 mysql-server \
90
+ php7.4 php7.4-common php7.4-cli libapache2-mod-php7.4 \
91
+ php7.4-xml php7.4-curl php7.4-mysql php7.4-gd php7.4-zip php7.4-intl php7.4-mbstring \
92
+ default-jdk openssh-server \
93
+ curl wget unzip axel expect vim net-tools ttyload ca-certificates apt-transport-https \
94
+ python3-requests || return 1
95
+ # 装了别的 PHP 版本时,命令行默认的 php 也指向 7.4
96
+ sudoS update-alternatives --set php /usr/bin/php7.4
97
+ sudoS update-alternatives --set phar /usr/bin/phar7.4 2>/dev/null
98
+ sudoS update-alternatives --set phar.phar /usr/bin/phar.phar7.4 2>/dev/null
99
+ sudoS systemctl restart apache2 2>/dev/null || sudoS service apache2 restart
100
+ }
101
+ must apt install_packages
157
102
 
158
- echo ""
159
- echo "#######################################################################"
160
- echo "# Auto Config Complete! #"
161
- echo "# V 1.0.0 #"
162
- echo "#######################################################################"
163
- echo ""
103
+ # ---------------------------------------------------------------- 2. 后端代码
104
+ download_backend() {
105
+ bash "$DIR/files/getFile.sh" && [ -f "$BACKEND_SRC/package.json" ]
106
+ }
107
+ must download download_backend
108
+
109
+ # ---------------------------------------------------------------- 3. 数据库
110
+ setup_database() {
111
+ # 先确保 MySQL 在跑(没有 systemd 的 WSL 不会自动起),否则下面的判断会把已有的库当成没有
112
+ sudoS service mysql start 2>/dev/null
113
+ # 没有 systemd 时 socket 目录可能是 700,aaden 跑数据库迁移会连不上(SQLSTATE 2002 Permission denied)
114
+ sudoS chmod 755 /var/run/mysqld 2>/dev/null
115
+ if sudoS mysql -uroot -e 'USE aaden' 2>/dev/null || sudoS test -d /var/lib/mysql/aaden; then
116
+ echo "数据库 aaden 已存在,跳过初始化(重跑装机不会覆盖门店数据)"
117
+ return 0
118
+ fi
119
+ sudoS bash "$DIR/scureSql.sh" "$PW"
120
+ sudoS sh -c "mysql -uroot < '$BACKEND_SRC/new.sql'" && sudoS mysql -uroot -e 'USE aaden'
121
+ }
122
+ must db setup_database
123
+
124
+ # ---------------------------------------------------------------- 4. 部署后端
125
+ deploy_backend() {
126
+ # cp 而不是 mv:重跑时目标目录已存在,mv 会失败
127
+ sudoS cp -a "$BACKEND_SRC/." "$WEB/" || return 1
128
+ sudoS rm -rf "$BACKEND_SRC"
129
+ sudoS chown -hR www-data:www-data "$WEB"
130
+ sudoS chmod -R 777 "$WEB/Resource"
131
+ sudoS chmod +x "$WEB/crontab.sh" "$WEB/PHP/vendor/bin/phinx" "$WEB/PHP/vendor/robmorgan/phinx/bin/phinx"
132
+ sudoS systemctl restart apache2 2>/dev/null || sudoS service apache2 restart
133
+ sleep 2
134
+ curl -fsS -m 10 http://localhost/package.json | grep '"version"'
135
+ }
136
+ must deploy deploy_backend
164
137
 
165
- echo ""
166
- echo "#######################################################################"
167
- echo "# Install TeamViewer #"
168
- echo "# V 1.0.0 #"
169
- echo "#######################################################################"
170
- echo ""
138
+ # ---------------------------------------------------------------- 5. 设备号:配置、主机名、ngrok、上报
139
+ must device aaden-cli set-device-id "$DEVICE_ID"
171
140
 
172
- cd || exit
173
- wget https://download.teamviewer.com/download/linux/teamviewer_amd64.deb
174
- sudo apt -y install ./teamviewer_amd64.deb
141
+ # ---------------------------------------------------------------- 6. 数据库迁移
142
+ must migrate sh -c "cd '$WEB/PHP' && vendor/bin/phinx migrate"
175
143
 
176
- wget https://aaden.online/AadenOS/background.png
144
+ # ---------------------------------------------------------------- 7. 系统配置(失败不中止,最后的自检会标出来)
145
+ add_groups() {
146
+ # 打印机(lp)、读日志(adm)、aaden 能 sudo;www-data 要能访问 USB 打印机
147
+ sudoS usermod -a -G lp,root,adm,sudo aaden && sudoS usermod -a -G lp,root www-data
148
+ }
149
+ step groups add_groups
150
+ step patch aaden-cli patch
151
+ # 日结物化守护进程:每日数据库备份和 DSFinV-K 日结物化都靠它
152
+ step gdpdu aaden-cli auto-write-gdpdu
153
+ # aaden 和 root 的定时任务整份覆盖写(do-log 上报、每日自动更新等)
154
+ step cron aaden-cli fix-cronjob
155
+ # 升级 aaden-cli、跑补丁、后端 light-update、同步 AppCenter 前端
156
+ step upgrade aaden-cli upgrade
157
+
158
+ if ! is_wsl; then
159
+ install_teamviewer() {
160
+ local deb
161
+ deb=$(mktemp --suffix=.deb)
162
+ wget -q -O "$deb" https://download.teamviewer.com/download/linux/teamviewer_amd64.deb \
163
+ && sudoS env DEBIAN_FRONTEND=noninteractive apt-get -y install "$deb"
164
+ local code=$?
165
+ rm -f "$deb"
166
+ wget -q -O "$HOME/background.png" https://aaden.online/AadenOS/background.png
167
+ return $code
168
+ }
169
+ step teamviewer install_teamviewer
170
+ fi
177
171
 
172
+ # ---------------------------------------------------------------- 8. 自检
173
+ banner "自检"
174
+ CHECKS=""
175
+ BAD=""
176
+ check() { # check <key> <说明> <命令…>
177
+ local key=$1 label=$2
178
+ shift 2
179
+ if "$@" >/dev/null 2>&1; then
180
+ CHECKS="$CHECKS $key=ok"
181
+ echo " ✓ $label"
182
+ else
183
+ CHECKS="$CHECKS $key=FAIL"
184
+ BAD="$BAD $label"
185
+ echo " ✗ $label"
186
+ fi
187
+ }
188
+ NGROK_HOST="ik$(printf '%04d' "$DEVICE_ID").ngrok.aaden.io"
178
189
 
190
+ check_cloud() {
191
+ aaden-cli do-log >/dev/null 2>&1
192
+ curl -fsS -m 15 "https://cloud-v2.aaden.io/deviceLog/install-check/$DEVICE_ID" \
193
+ | python3 -c 'import json,sys; m = json.load(sys.stdin).get("lastReportMinutesAgo"); sys.exit(0 if m is not None and m <= 10 else 1)'
194
+ }
195
+ check_ngrok() { # 隧道刚起来时要等几秒
196
+ local i
197
+ for i in 1 2 3 4 5 6; do
198
+ curl -fsS -m 10 "https://$NGROK_HOST/package.json" | grep -q '"version"' && return 0
199
+ sleep 10
200
+ done
201
+ return 1
202
+ }
203
+ check_gdpdu() {
204
+ systemctl is-active --quiet aaden-gdpdu.service 2>/dev/null \
205
+ || pgrep -f 'autoWriteGdpdu\.php' >/dev/null \
206
+ || [ -f /etc/cron.d/aaden-gdpdu ]
207
+ }
208
+ check_cron() {
209
+ crontab -l 2>/dev/null | grep -q 'do-log' && sudoS crontab -l -u root 2>/dev/null | grep -q 'auto-upgrade'
210
+ }
179
211
 
212
+ check_id() {
213
+ [ "$(awk -F= '/^\[/ { s = $0 } s ~ /^\[Device\]/ && $1 ~ /^[ \t]*DeviceId[ \t]*$/ { gsub(/[ \t"\r]/, "", $2); print $2; exit }' "$WEB/Resource/config/config.ini")" = "$DEVICE_ID" ]
214
+ }
180
215
 
216
+ check backend "后端在跑(http://localhost/package.json)" sh -c 'curl -fsS -m 10 http://localhost/package.json | grep -q version'
217
+ check id "设备号写入配置($DEVICE_ID)" check_id
218
+ check cloud "云端收到本机上报(ERP 门店列表「机器」列显示就绪)" check_cloud
219
+ check ngrok "远程访问 https://$NGROK_HOST" check_ngrok
220
+ check gdpdu "日结守护进程 aaden-gdpdu(没有它就没有每日备份)" check_gdpdu
221
+ check cron "定时任务(上报、每日自动更新)" check_cron
222
+
223
+ FAILED_STEPS=$(echo "$STEPS" | tr ' ' '\n' | grep -v '=0/' | cut -d= -f1 | tr '\n' ' ')
224
+ if [ -z "$BAD" ] && [ -z "${FAILED_STEPS// /}" ]; then
225
+ report 0 " [自检${CHECKS}]"
226
+ banner "装机完成,设备号 $DEVICE_ID,可以交付"
227
+ exit 0
228
+ fi
229
+ report 1 " [自检${CHECKS}]"
230
+ banner "装机跑完了,但有问题要处理"
231
+ [ -n "${FAILED_STEPS// /}" ] && echo "失败的步骤:$FAILED_STEPS"
232
+ [ -n "$BAD" ] && echo "没通过的自检:$BAD"
233
+ echo "处理完可以重新运行同一条命令。日志:$LOG"
234
+ exit 1
@@ -0,0 +1,104 @@
1
+ #!/bin/bash
2
+ # 装机前检查设备号:这个号在 ERP 是哪家店、是不是已经有收银机在用。拦住输错号、用了别家号的「撞号」——
3
+ # 同一个号装两台机器,云端的上报、备份、报表、远程连接(ngrok ik 号)会互相覆盖。
4
+ #
5
+ # 退出码 0 = 继续装;1 = 号不对或装机同事取消。
6
+ # 连不上云端只警告、不挡安装(现场网络常常不好)。确实要跳过检查:AADEN_SKIP_DEVICE_CHECK=1
7
+ DeviceId="$1"
8
+ CLOUD="${AADEN_CLOUD_URL:-https://cloud-v2.aaden.io}"
9
+
10
+ [ -n "$AADEN_SKIP_DEVICE_CHECK" ] && { echo "跳过设备号检查(AADEN_SKIP_DEVICE_CHECK)"; exit 0; }
11
+ if ! [[ "$DeviceId" =~ ^[0-9]+$ ]]; then
12
+ echo "设备号必须是数字:'$DeviceId'"
13
+ exit 1
14
+ fi
15
+
16
+ # 提问走 /dev/tty:脚本的标准输入可能被管道占着。没有终端(自动化装机)时 ask 返回空串
17
+ HAVE_TTY=""
18
+ { exec 3</dev/tty; } 2>/dev/null && HAVE_TTY=1
19
+ ask() {
20
+ local answer=""
21
+ [ -n "$HAVE_TTY" ] && read -r -p "$1" answer <&3 2>/dev/tty
22
+ echo "$answer"
23
+ }
24
+
25
+ URL="$CLOUD/deviceLog/install-check/$DeviceId"
26
+ JSON=$(curl -fsS -m 15 "$URL" 2>/dev/null || wget -qO- -T 15 "$URL" 2>/dev/null)
27
+
28
+ # 第一行是结论(OK / IN_USE / NO_STORE / ERROR),后面是给装机同事看的说明
29
+ REPORT=$(python3 - "$JSON" <<'PY'
30
+ import json, sys
31
+ try:
32
+ d = json.loads(sys.argv[1])
33
+ store, machine = d.get("store"), d.get("machine")
34
+ except Exception:
35
+ print("ERROR")
36
+ sys.exit()
37
+
38
+ status = {"AwaitingInstallation": "等待安装", "Installed": "已安装", "Closed": "已关停", "StopService": "停止服务"}
39
+
40
+ def when(v):
41
+ return v[:16].replace("T", " ") if v else "—"
42
+
43
+ def ago(minutes):
44
+ if minutes is None:
45
+ return "—"
46
+ if minutes < 60:
47
+ return f"{max(minutes, 1)} 分钟前"
48
+ if minutes < 24 * 60:
49
+ return f"{round(minutes / 60)} 小时前"
50
+ return f"{round(minutes / 60 / 24)} 天前"
51
+
52
+ if not store:
53
+ print("NO_STORE")
54
+ sys.exit()
55
+
56
+ parts = [p for p in (store.get("displayCode"), store.get("city"), status.get(store.get("status"), store.get("status"))) if p]
57
+ store_line = f"ERP 门店「{store.get('name') or '—'}」({','.join(parts)})"
58
+
59
+ if machine:
60
+ print("IN_USE")
61
+ print(f" 收银机里的餐厅名:{machine.get('posName') or '—'}")
62
+ print(f" 第一次上报 {when(machine.get('firstReportAt'))},最近上报 {ago(d.get('lastReportMinutesAgo'))}")
63
+ print(f" {store_line}")
64
+ else:
65
+ print("OK")
66
+ print(f" {store_line}")
67
+ print(" 云端还没收到过这个号的收银机上报")
68
+ PY
69
+ )
70
+ VERDICT=$(echo "$REPORT" | head -n 1)
71
+ DETAIL=$(echo "$REPORT" | tail -n +2)
72
+
73
+ echo ""
74
+ echo "#######################################################################"
75
+ echo "检查设备号 $DeviceId"
76
+ case "$VERDICT" in
77
+ OK)
78
+ echo "$DETAIL"
79
+ # 没有终端可问(自动化装机)时号也没人用,直接继续
80
+ if [ -n "$HAVE_TTY" ]; then
81
+ answer=$(ask "是这家店吗?[y/N] ")
82
+ [[ "$answer" =~ ^[yY] ]] || { echo "已取消。"; exit 1; }
83
+ fi
84
+ ;;
85
+ IN_USE)
86
+ echo "⚠ 这个号已经有收银机在用:"
87
+ echo "$DETAIL"
88
+ echo "同一个号装两台机器,云端的上报、备份、报表、远程连接会互相覆盖。"
89
+ echo "只有给这家店换机或重装才应该继续,而且旧机器要先关掉。"
90
+ answer=$(ask "确认继续请再输入一遍设备号(直接回车取消):")
91
+ [ "$answer" = "$DeviceId" ] || { echo "已取消。"; exit 1; }
92
+ ;;
93
+ NO_STORE)
94
+ echo "✗ ERP 里没有编号 $DeviceId 的门店:先在 ERP 建档,或者检查设备号有没有输错。"
95
+ echo " 确实要装:AADEN_SKIP_DEVICE_CHECK=1 再跑一次"
96
+ exit 1
97
+ ;;
98
+ *)
99
+ echo "⚠ 连不上云端($CLOUD),没法检查设备号有没有撞号,继续安装。"
100
+ sleep 3
101
+ ;;
102
+ esac
103
+ echo "#######################################################################"
104
+ exit 0