├── config.json ├── ehco.service ├── README.md └── ehco.sh /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "web_port": 9000, 3 | "web_token": "", 4 | "enable_ping": false, 5 | 6 | "relay_configs": [ 7 | 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /ehco.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=ehco 3 | After=network-online.target 4 | Wants=network-online.target systemd-networkd-wait-online.service 5 | 6 | [Service] 7 | Type=simple 8 | User=root 9 | Restart=always 10 | RestartSec=5 11 | DynamicUser=true 12 | ExecStart=/usr/bin/ehco -c /etc/ehco/config.json 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EasyEhco 2 | Ehco一键脚本 3 | 4 | A simple script to use Ehco Tunnel 5 | ## 国内中转可用 6 | ```bash 7 | wget -O ehco.sh https://linuxscript.netlify.app/ehco.sh && bash ehco.sh 8 | ``` 9 | ## 国外落地使用 10 | ```bash 11 | wget -O ehco.sh https://raw.githubusercontent.com/owogo/EasyEhco/main/ehco.sh && bash ehco.sh 12 | ``` 13 | 再次使用脚本: ```bash ehco.sh``` 14 | 15 | 感谢以下项目: 16 | 17 | [1] https://github.com/KANIKIG/Multi-EasyGost 18 | 19 | [2] https://github.com/Ehco1996/ehco 20 | 21 | [3] https://github.com/missuo/Ehcoo 22 | -------------------------------------------------------------------------------- /ehco.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #脚本版本 3 | Shell_Version="0.0.1" 4 | Info="${Green_font_prefix}[信息]${Font_color_suffix}" 5 | Error="${Red_font_prefix}[错误]${Font_color_suffix}" 6 | # Github: https://github.com/owogo/easyehco 7 | #================================================================= 8 | ehco_conf_path="/etc/ehco/config.json" 9 | raw_conf_path="/etc/ehco/rawconf" 10 | red='\033[0;31m' 11 | plain='\033[0m' 12 | 13 | Green_font_prefix="\033[32m" && Red_font_prefix="\033[31m" && Green_background_prefix="\033[42;37m" && Font_color_suffix="\033[0m" 14 | #确保本脚本在ROOT下运行 15 | [[ $EUID -ne 0 ]] && echo -e "[${red}错误${plain}]请以ROOT运行本脚本!" && exit 1 16 | 17 | check_sys(){ 18 | echo "现在开始检查你的系统是否支持" 19 | #判断是什么Linux系统 20 | if [[ -f /etc/redhat-release ]]; then 21 | release="Centos" 22 | elif cat /etc/issue | grep -q -E -i "debian"; then 23 | release="Debian" 24 | elif cat /etc/issue | grep -q -E -i "ubuntu"; then 25 | release="Ubuntu" 26 | elif cat /etc/issue | grep -q -E -i "centos|red hat|redhat"; then 27 | release="Centos" 28 | elif cat /proc/version | grep -q -E -i "debian"; then 29 | release="Debian" 30 | elif cat /proc/version | grep -q -E -i "ubuntu"; then 31 | release="Ubuntu" 32 | elif cat /proc/version | grep -q -E -i "centos|red hat|redhat"; then 33 | release="Centos" 34 | fi 35 | 36 | #判断Linux系统的具体版本和位数 37 | if [[ -s /etc/redhat-release ]]; then 38 | version=`grep -oE "[0-9.]+" /etc/redhat-release | cut -d . -f 1` 39 | else 40 | version=`grep -oE "[0-9.]+" /etc/issue | cut -d . -f 1` 41 | fi 42 | bit=`uname -m` 43 | if [[ ${bit} = "x86_64" ]]; then 44 | bit="amd64" 45 | else 46 | bit="arm64" 47 | fi 48 | 49 | #判断内核版本 50 | kernel_version=`uname -r | awk -F "-" '{print $1}'` 51 | kernel_version_full=`uname -r` 52 | net_congestion_control=`cat /proc/sys/net/ipv4/tcp_congestion_control | awk '{print $1}'` 53 | net_qdisc=`cat /proc/sys/net/core/default_qdisc | awk '{print $1}'` 54 | kernel_version_r=`uname -r | awk '{print $1}'` 55 | echo "系统版本为: $release $version $bit 内核版本为: $kernel_version_r" 56 | 57 | if [ $release = "Centos" ] 58 | then 59 | yum -y install wget 60 | sysctl_dir="/usr/lib/systemd/system/" 61 | full_sysctl_dir=${sysctl_dir}"ehco.service" 62 | elif [ $release = "Debian" ] 63 | then 64 | apt-get install wget 65 | sysctl_dir="/etc/systemd/system/" 66 | full_sysctl_dir=${sysctl_dir}"ehco.service" 67 | elif [ $release = "Ubuntu" ] 68 | then 69 | apt-get install wget 70 | sysctl_dir="/lib/systemd/system/" 71 | full_sysctl_dir=${sysctl_dir}"ehco.service" 72 | else 73 | echo -e "[${red}错误${plain}]不支持当前系统" 74 | exit 1 75 | fi 76 | } 77 | 78 | function checknew() { 79 | checknew=$(ehco -v 2>&1 | grep "Version=") 80 | check_new_ver 81 | echo "你的ehco版本为:""$checknew""" 82 | echo -n 是否更新\(y/n\)\: 83 | read checknewnum 84 | if test $checknewnum = "y"; then 85 | cp -r /etc/ehco /tmp/ 86 | Install_ct 87 | rm -rf /etc/ehco 88 | mv /tmp/ehco /etc/ 89 | systemctl restart ehco.service 90 | else 91 | exit 0 92 | fi 93 | } 94 | 95 | function check_new_ver() { 96 | ct_new_ver=$(wget --no-check-certificate -qO- -t2 -T3 https://api.github.com/repos/ehco1996/ehco/releases/latest | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g;s/v//g') 97 | if [[ -z ${ct_new_ver} ]]; then 98 | ct_new_ver=$(ehco -v | awk -F " " '{print $3}') 99 | echo -e "${Error} ehco 最新版本获取失败,正在下载v${ct_new_ver}版" 100 | else 101 | echo -e "${Info} ehco 目前最新版本为 ${ct_new_ver}" 102 | fi 103 | } 104 | function check_file() { 105 | if test ! -d "$sysctl_dir"; then 106 | mkdir $sysctl_dir 107 | chmod -R 777 $sysctl_dir 108 | fi 109 | } 110 | function check_nor_file() { 111 | rm -rf "$(pwd)"/ehco 112 | rm -rf "$(pwd)"/ehco.service 113 | rm -rf "$(pwd)"/config.json 114 | rm -rf /etc/ehco 115 | rm -rf /lib/systemd/system/ehco.service 116 | rm -rf /etc/systemd/system/ehco.service 117 | rm -rf /lib/systemd/system/ehco.service 118 | rm -rf /usr/bin/ehco 119 | } 120 | function Install_ct() { 121 | check_nor_file 122 | check_sys 123 | check_file 124 | check_new_ver 125 | rm -rf ehco_"$ct_new_ver"_linux_"$bit" 126 | wget --no-check-certificate https://github.com/Ehco1996/ehco/releases/download/v"$ct_new_ver"/ehco_"$ct_new_ver"_linux_"$bit" -O ehco 127 | chmod +x ehco 128 | mv ehco /usr/bin 129 | wget --no-check-certificate https://raw.githubusercontent.com/owogo/easyehco/master/ehco.service && mv ehco.service $sysctl_dir 130 | mkdir /etc/ehco && wget --no-check-certificate https://raw.githubusercontent.com/owogo/easyehco/master/config.json && mv config.json /etc/ehco 131 | systemctl daemon-reload 132 | systemctl start ehco.service 133 | systemctl enable ehco.service 134 | systemctl restart ehco.service 135 | echo "" 136 | clear 137 | echo "------------------------------" 138 | if test -a /usr/bin/ehco -a $full_sysctl_dir -a /etc/ehco/config.json; then 139 | echo "ehco安装成功" 140 | rm -rf "$(pwd)"/ehco 141 | rm -rf "$(pwd)"/ehco.service 142 | rm -rf "$(pwd)"/config.json 143 | else 144 | echo "ehco没有安装成功" 145 | rm -rf "$(pwd)"/ehco 146 | rm -rf "$(pwd)"/ehco.service 147 | rm -rf "$(pwd)"/config.json 148 | rm -rf "$(pwd)"/ehco.sh 149 | fi 150 | sleep 3s 151 | start_menu 152 | } 153 | function Uninstall_ct() { 154 | rm -rf /usr/bin/ehco 155 | rm -rf $full_sysctl_dir 156 | rm -rf /etc/ehco 157 | echo "ehco已经成功删除" 158 | } 159 | function Start_ct() { 160 | systemctl start ehco.service 161 | echo "已启动" 162 | sleep 3s 163 | start_menu 164 | } 165 | function Stop_ct() { 166 | systemctl stop ehco.service 167 | echo "已停止" 168 | sleep 3s 169 | start_menu 170 | } 171 | function Restart_ct() { 172 | rm -rf /etc/ehco/config.json 173 | confstart 174 | writeconf 175 | conflast 176 | systemctl restart ehco.service 177 | echo "已重读配置并重启" 178 | sleep 3s 179 | start_menu 180 | } 181 | function read_protocol() { 182 | echo -e "请问您要设置哪种功能: " 183 | echo -e "-----------------------------------" 184 | echo -e "[1] tcp+udp流量转发, 不加密" 185 | echo -e "说明: 一般设置在国内中转机上" 186 | echo -e "-----------------------------------" 187 | echo -e "[2] 加密隧道流量转发" 188 | echo -e "说明: 用于转发原本加密等级较低的流量, 一般设置在国内中转机上" 189 | echo -e " 选择此协议意味着你还有一台机器用于接收此加密流量, 之后须在那台机器上配置协议[3]进行对接" 190 | echo -e "-----------------------------------" 191 | echo -e "[3] 解密由ehco传输而来的流量并转发" 192 | echo -e "说明: 对于经由ehco加密中转的流量, 通过此选项进行解密并转发给本机的代理服务端口或转发给其他远程机器" 193 | echo -e " 一般设置在用于接收中转流量的国外机器上" 194 | echo -e "-----------------------------------" 195 | read -p "请选择: " numprotocol 196 | 197 | if [ "$numprotocol" == "1" ]; then 198 | flag_a="nonencrypt" 199 | elif [ "$numprotocol" == "2" ]; then 200 | encrypt 201 | elif [ "$numprotocol" == "3" ]; then 202 | decrypt 203 | else 204 | echo "type error, please try again" 205 | exit 206 | fi 207 | } 208 | 209 | function encrypt() { 210 | echo -e "请问您要设置的转发传输类型: " 211 | echo -e "-----------------------------------" 212 | echo -e "[1] ws隧道" 213 | echo -e "[2] wss隧道" 214 | echo -e "[3] mwss隧道" 215 | echo -e "注意: 同一则转发,中转与落地传输类型必须对应!" 216 | echo -e "-----------------------------------" 217 | read -p "请选择转发传输类型: " numencrypt 218 | 219 | if [ "$numencrypt" == "1" ]; then 220 | flag_a="encryptws" 221 | elif [ "$numencrypt" == "2" ]; then 222 | flag_a="encryptwss" 223 | elif [ "$numencrypt" == "3" ]; then 224 | flag_a="encryptmwss" 225 | else 226 | echo "type error, please try again" 227 | exit 228 | fi 229 | } 230 | 231 | function decrypt() { 232 | echo -e "请问您要设置的解密传输类型: " 233 | echo -e "-----------------------------------" 234 | echo -e "[1] ws" 235 | echo -e "[2] wss" 236 | echo -e "[3] mwss" 237 | echo -e "注意: 同一则转发,中转与落地传输类型必须对应!" 238 | echo -e "-----------------------------------" 239 | read -p "请选择解密传输类型: " numdecrypt 240 | 241 | if [ "$numdecrypt" == "1" ]; then 242 | flag_a="decryptws" 243 | elif [ "$numdecrypt" == "2" ]; then 244 | flag_a="decryptwss" 245 | elif [ "$numdecrypt" == "3" ]; then 246 | flag_a="decryptmwss" 247 | else 248 | echo "type error, please try again" 249 | exit 250 | fi 251 | } 252 | 253 | function method() { 254 | if [ $i -ge 1 ]; then 255 | if [ "$is_encrypt" == "nonencrypt" ]; then 256 | echo " \"listen\": \"0.0.0.0:$s_port\", 257 | \"listen_type\": \"raw\", 258 | \"transport_type\": \"raw\", 259 | \"tcp_remotes\": [\"$d_ip:$d_port\"], 260 | \"udp_remotes\": [\"$d_ip:$d_port\"]" >>$ehco_conf_path 261 | elif [ "$is_encrypt" == "encryptws" ]; then 262 | echo " \"listen\": \"0.0.0.0:$s_port\", 263 | \"listen_type\": \"raw\", 264 | \"transport_type\": \"ws\", 265 | \"tcp_remotes\": [\"ws://$d_ip:$d_port\"], 266 | \"udp_remotes\": [\"ws://$d_ip:$d_port\"]" >>$ehco_conf_path 267 | elif [ "$is_encrypt" == "encryptwss" ]; then 268 | echo " \"listen\": \"0.0.0.0:$s_port\", 269 | \"listen_type\": \"raw\", 270 | \"transport_type\": \"wss\", 271 | \"tcp_remotes\": [\"wss://$d_ip:$d_port\"], 272 | \"udp_remotes\": [\"wss://$d_ip:$d_port\"]" >>$ehco_conf_path 273 | 274 | elif [ "$is_encrypt" == "encryptmwss" ]; then 275 | echo " \"listen\": \"0.0.0.0:$s_port\", 276 | \"listen_type\": \"raw\", 277 | \"transport_type\": \"mwss\", 278 | \"tcp_remotes\": [\"wss://$d_ip:$d_port\"], 279 | \"udp_remotes\": [\"wss://$d_ip:$d_port\"]" >>$ehco_conf_path 280 | 281 | elif [ "$is_encrypt" == "decryptws" ]; then 282 | echo " \"listen\": \"0.0.0.0:$s_port\", 283 | \"listen_type\": \"ws\", 284 | \"transport_type\": \"raw\", 285 | \"tcp_remotes\": [\"$d_ip:$d_port\"], 286 | \"udp_remotes\": [\"$d_ip:$d_port\"]" >>$ehco_conf_path 287 | elif [ "$is_encrypt" == "decryptwss" ]; then 288 | echo " \"listen\": \"0.0.0.0:$s_port\", 289 | \"listen_type\": \"wss\", 290 | \"transport_type\": \"raw\", 291 | \"tcp_remotes\": [\"$d_ip:$d_port\"], 292 | \"udp_remotes\": [\"$d_ip:$d_port\"]" >>$ehco_conf_path 293 | elif [ "$is_encrypt" == "decryptmwss" ]; then 294 | echo " \"listen\": \"0.0.0.0:$s_port\", 295 | \"listen_type\": \"mwss\", 296 | \"transport_type\": \"raw\", 297 | \"tcp_remotes\": [\"$d_ip:$d_port\"], 298 | \"udp_remotes\": [\"$d_ip:$d_port\"]" >>$ehco_conf_path 299 | else 300 | echo "config error" 301 | fi 302 | else 303 | echo "config error" 304 | exit 305 | fi 306 | } 307 | 308 | function read_s_port() { 309 | echo -e "请问你要将本机哪个端口接收到的流量进行转发?" 310 | read -p "请输入: " flag_b 311 | } 312 | function read_d_ip() { 313 | echo -e "------------------------------------------------------------------" 314 | echo -e "请问你要将本机从${flag_b}接收到的流量转发向哪个IP或域名?" 315 | echo -e "注: IP既可以是[远程机器/当前机器]的公网IP, 也可是以本机本地回环IP(即127.0.0.1)" 316 | echo -e "具体IP地址的填写, 取决于接收该流量的服务正在监听的IP,默认为127.0.0.1" 317 | read -p "请输入: " flag_c 318 | if [ ! -n "$flag_c" ]; then 319 | flag_c="127.0.0.1" 320 | fi 321 | } 322 | function read_d_port() { 323 | echo -e "------------------------------------------------------------------" 324 | echo -e "请问你要将本机从${flag_b}接收到的流量转发向${flag_c}的哪个端口?" 325 | read -p "请输入: " flag_d 326 | } 327 | function writerawconf() { 328 | echo $flag_a"/""$flag_b""#""$flag_c""#""$flag_d" >>$raw_conf_path 329 | } 330 | function rawconf() { 331 | read_protocol 332 | read_s_port 333 | read_d_ip 334 | read_d_port 335 | writerawconf 336 | } 337 | function eachconf_retrieve() { 338 | d_server=${trans_conf#*#} 339 | d_port=${d_server#*#} 340 | d_ip=${d_server%#*} 341 | flag_s_port=${trans_conf%%#*} 342 | s_port=${flag_s_port#*/} 343 | is_encrypt=${flag_s_port%/*} 344 | } 345 | function confstart() { 346 | echo "{ 347 | \"enable_ping\": false, 348 | 349 | \"relay_configs\": [ " >>$ehco_conf_path 350 | } 351 | function multiconfstart() { 352 | echo " { ">>$ehco_conf_path 353 | } 354 | function conflast() { 355 | echo " ] 356 | }" >>$ehco_conf_path 357 | } 358 | 359 | function multiconflast() { 360 | if [ $i -eq $count_line ]; then 361 | echo " }" >>$ehco_conf_path 362 | else 363 | echo " }," >>$ehco_conf_path 364 | fi 365 | } 366 | 367 | function writeconf() { 368 | count_line=$(awk 'END{print NR}' $raw_conf_path) 369 | for ((i = 1; i <= $count_line; i++)); do 370 | if [ $i -eq 1 ]; then 371 | trans_conf=$(sed -n "${i}p" $raw_conf_path) 372 | eachconf_retrieve 373 | multiconfstart 374 | method 375 | multiconflast 376 | elif [ $i -gt 1 ]; then 377 | trans_conf=$(sed -n "${i}p" $raw_conf_path) 378 | eachconf_retrieve 379 | multiconfstart 380 | method 381 | multiconflast 382 | fi 383 | done 384 | } 385 | function show_all_conf() { 386 | echo -e " EHCO 配置 " 387 | echo -e "--------------------------------------------------------" 388 | echo -e "序号|方法\t |本地端口\t|目的地地址:目的地端口" 389 | echo -e "--------------------------------------------------------" 390 | 391 | count_line=$(awk 'END{print NR}' $raw_conf_path) 392 | for ((i = 1; i <= $count_line; i++)); do 393 | trans_conf=$(sed -n "${i}p" $raw_conf_path) 394 | eachconf_retrieve 395 | 396 | if [ "$is_encrypt" == "nonencrypt" ]; then 397 | str="不加密中转" 398 | elif [ "$is_encrypt" == "encryptws" ]; then 399 | str=" ws隧道 " 400 | elif [ "$is_encrypt" == "encryptwss" ]; then 401 | str=" wss隧道 " 402 | elif [ "$is_encrypt" == "encryptmwss" ]; then 403 | str=" mwss隧道 " 404 | elif [ "$is_encrypt" == "decryptws" ]; then 405 | str=" ws解密 " 406 | elif [ "$is_encrypt" == "decryptwss" ]; then 407 | str=" wss解密 " 408 | elif [ "$is_encrypt" == "decryptmwss" ]; then 409 | str=" mwss解密 " 410 | else 411 | str="" 412 | fi 413 | 414 | echo -e " $i |$str |$s_port\t|$d_ip:$d_port" 415 | echo -e "--------------------------------------------------------" 416 | done 417 | } 418 | 419 | cron_restart() { 420 | echo -e "------------------------------------------------------------------" 421 | echo -e "ehco定时重启任务: " 422 | echo -e "-----------------------------------" 423 | echo -e "[1] 配置ehco定时重启任务" 424 | echo -e "[2] 删除ehco定时重启任务" 425 | echo -e "-----------------------------------" 426 | read -p "请选择: " numcron 427 | if [ "$numcron" == "1" ]; then 428 | echo -e "------------------------------------------------------------------" 429 | echo -e "ehco定时重启任务类型: " 430 | echo -e "-----------------------------------" 431 | echo -e "[1] 每?小时重启" 432 | echo -e "[2] 每日?点重启" 433 | echo -e "-----------------------------------" 434 | read -p "请选择: " numcrontype 435 | if [ "$numcrontype" == "1" ]; then 436 | echo -e "-----------------------------------" 437 | read -p "每?小时重启: " cronhr 438 | echo "0 0 */$cronhr * * ? * systemctl restart ehco.service" >>/etc/crontab 439 | echo -e "定时重启设置成功!" 440 | elif [ "$numcrontype" == "2" ]; then 441 | echo -e "-----------------------------------" 442 | read -p "每日?点重启: " cronhr 443 | echo "0 0 $cronhr * * ? systemctl restart ehco.service" >>/etc/crontab 444 | echo -e "定时重启设置成功!" 445 | else 446 | echo "type error, please try again" 447 | exit 448 | fi 449 | elif [ "$numcron" == "2" ]; then 450 | sed -i "/ehco/d" /etc/crontab 451 | echo -e "定时重启任务删除完成!" 452 | else 453 | echo "type error, please try again" 454 | exit 455 | fi 456 | } 457 | function start_menu(){ 458 | clear 459 | echo && echo -e " ehco 一键安装配置脚本 460 | 功能: 1.tcp+udp不加密转发, 2.中转机加密转发, 3.落地机解密对接转发 461 | 帮助文档:https://github.com/owogo/EasyEhco 462 | ${Green_font_prefix}0.${Font_color_suffix} 退出脚本 463 | ${Green_font_prefix}1.${Font_color_suffix} 安装 ehco 464 | ${Green_font_prefix}2.${Font_color_suffix} 更新 ehco 465 | ${Green_font_prefix}3.${Font_color_suffix} 卸载 ehco 466 | ———————————— 467 | ${Green_font_prefix}4.${Font_color_suffix} 启动 ehco 468 | ${Green_font_prefix}5.${Font_color_suffix} 停止 ehco 469 | ${Green_font_prefix}6.${Font_color_suffix} 重启 ehco 470 | ———————————— 471 | ${Green_font_prefix}7.${Font_color_suffix} 新增ehco转发配置 472 | ${Green_font_prefix}8.${Font_color_suffix} 查看现有ehco配置 473 | ${Green_font_prefix}9.${Font_color_suffix} 删除一则ehco配置 474 | ———————————— 475 | ${Green_font_prefix}10.${Font_color_suffix} ehco定时重启配置 476 | ${Green_font_prefix}11.${Font_color_suffix} 更新脚本 477 | 478 | ————————————" && echo 479 | read -e -p " 请输入数字 [0-11]:" num 480 | case "$num" in 481 | 0) 482 | exit 1 483 | ;; 484 | 1) 485 | Install_ct 486 | ;; 487 | 2) 488 | checknew 489 | ;; 490 | 3) 491 | Uninstall_ct 492 | ;; 493 | 4) 494 | Start_ct 495 | ;; 496 | 5) 497 | Stop_ct 498 | ;; 499 | 6) 500 | Restart_ct 501 | ;; 502 | 7) 503 | rawconf 504 | rm -rf /etc/ehco/config.json 505 | confstart 506 | writeconf 507 | conflast 508 | systemctl restart ehco.service 509 | echo -e "配置已生效,当前配置如下" 510 | echo -e "--------------------------------------------------------" 511 | show_all_conf 512 | ;; 513 | 8) 514 | show_all_conf 515 | ;; 516 | 9) 517 | show_all_conf 518 | read -p "请输入你要删除的配置编号:" numdelete 519 | if echo $numdelete | grep -q '[0-9]'; then 520 | sed -i "${numdelete}d" $raw_conf_path 521 | rm -rf /etc/ehco/config.json 522 | confstart 523 | writeconf 524 | conflast 525 | systemctl restart ehco.service 526 | echo -e "配置已删除,服务已重启" 527 | else 528 | echo "请输入正确数字" 529 | fi 530 | sleep 3s 531 | start_menu 532 | ;; 533 | 10) 534 | cron_restart 535 | ;; 536 | 11) 537 | rm ehco.sh 538 | wget -O ehco.sh https://raw.githubusercontent.com/owogo/EasyEhco/main/ehco.sh && bash ehco.sh 539 | ;; 540 | *) 541 | echo "请输入正确数字" 542 | sleep 3s 543 | start_menu 544 | ;; 545 | esac 546 | } 547 | start_menu "first" 548 | --------------------------------------------------------------------------------