#! /bin/bash # chkconfig: 2345 55 25 # Description: Startup script for Ngrok on Debian. Place in /etc/init.d and # run 'update-rc.d -f ngrokd defaults', or use the appropriate command on your # distro. For CentOS/Redhat run: 'chkconfig --add ngrokd' #======================================================= # System Required: CentOS/Debian/Ubuntu (32bit/64bit) # Description: Manager for Ngrok, Written by Clang # Author: Clang # Intro: http://clangcn.com #======================================================= ### BEGIN INIT INFO # Provides: ngrok # Required-Start: $all # Required-Stop: $all # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: starts the ngrok # Description: starts ngrok using start-stop ### END INIT INFO # Source function library if [ -f /etc/rc.d/init.d/functions ]; then . /etc/rc.d/init.d/functions # Check that networking is up. [ ${NETWORKING} ="yes" ] || exit 0 fi PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin ProgramName="Ngrok" ProGramInstallPath="/usr/local/ngrok" ProgramPath="/usr/local/ngrok/bin" NAME=ngrokd BIN=${ProgramPath}/${NAME} CONFIGFILE=${ProGramInstallPath}/.ngrok_config.sh LOGFILE=${ProGramInstallPath}/ngrok.log SCRIPTNAME=/etc/init.d/${NAME} PID_DIR=/var/run PID_FILE=${PID_DIR}/ngrok_clang.pid version="8.1" manage_port="4446" RET_VAL=0 [ -x $BIN ] || exit 0 if [ ! -d $PID_DIR ]; then mkdir -p $PID_DIR if [ $? -ne 0 ]; then echo "Creating PID directory $PID_DIR failed" exit 1 fi fi fun_clangcn() { echo "" echo "+----------------------------------------------+" echo "| Manager for Ngrok, Written by Clang |" echo "+----------------------------------------------+" echo "| Intro: http://clang.cn/ |" echo "+----------------------------------------------+" echo "" } fun_check_run() { PID=`ps -ef | grep -v grep | grep -i "${BIN}" | awk '{print $2}'` if [ ! -z $PID ]; then return 0 else return 1 fi } fun_load_config(){ if [ ! -r ${CONFIGFILE} ]; then echo "config file ${CONFIGFILE} not found" return 1 else . ${CONFIGFILE} log_level="" [ -n "${loglevel}" ] && log_level=" -log-level=\"${loglevel}\"" cd ${ProGramInstallPath} fi } fun_check_port(){ fun_load_config strHttpPort="" strHttpsPort="" strRemotePort="" strManPort="" strHttpPort=`netstat -ntl | grep "\b:${http_port}\b"` strHttpsPort=`netstat -ntl | grep "\b:${https_port}\b"` strRemotePort=`netstat -ntl | grep "\b:${remote_port}\b"` strManagePort=`netstat -ntl | grep "\b:${manage_port}\b"` if [ -n "${strHttpPort}" ] || [ -n "${strHttpsPort}" ] || [ -n "${strRemotePort}" ] || [ -n "${strManagePort}" ]; then [ -n "${strHttpPort}" ] && str_http_port="\"${http_port}\" " [ -n "${strHttpsPort}" ] && str_https_port="\"${https_port}\" " [ -n "${strRemotePort}" ] && str_remote_port="\"${remote_port}\" " [ -n "${strManagePort}" ] && str_manage_port="\"${manage_port}\" " echo "" echo "Error: Port ${str_http_port}${str_https_port}${str_remote_port}${str_manage_port}is used,view relevant port:" [ -n "${strHttpPort}" ] && netstat -ntlp | grep "\b:${http_port}\b" [ -n "${strHttpsPort}" ] && netstat -ntlp | grep "\b:${https_port}\b" [ -n "${strRemotePort}" ] && netstat -ntlp | grep "\b:${remote_port}\b" [ -n "${strManagePort}" ] && netstat -ntlp | grep "\b:${manage_port}\b" return 1 fi } fun_randstr(){ index=0 strRandomPass="" for i in {a..z}; do arr[index]=$i; index=`expr ${index} + 1`; done for i in {A..Z}; do arr[index]=$i; index=`expr ${index} + 1`; done for i in {0..9}; do arr[index]=$i; index=`expr ${index} + 1`; done for i in {1..16}; do strRandomPass="$strRandomPass${arr[$RANDOM%$index]}"; done echo $strRandomPass } fun_start() { if [ "${arg1}" = "start" ]; then fun_clangcn fi if [ ! -d $PID_DIR ]; then mkdir -p $PID_DIR || echo "failed creating PID directory ${PID_DIR}"; exit 1 fi if [ -f ${PID_FILE} ]; then read PID < ${PID_FILE} echo "$NAME (pid $PID) is already running..." exit 0 fi echo -n "Starting ${ProgramName}: " fun_check_port fun_load_config ${BIN} -domain="$dns" -httpAddr=":$http_port" -httpsAddr=":$https_port" -pass="$pass" -tlsCrt="$srtCRT" -tlsKey="$strKey" -tunnelAddr=":$remote_port"${log_level} > ${LOGFILE} 2>&1 & RETVAL=$? PID=$(ps -ef | grep -v grep | grep -i ${BIN} | awk '{print $2}') echo ${PID} > ${PID_FILE} if [ -f /etc/rc.d/init.d/functions ]; then [ $RETVAL -eq 0 ] && success else if fun_check_run; then echo " [ok]" else echo " [FAILED]" RETVAL=1 fi fi } fun_stop(){ if [ "${arg1}" = "stop" ] || [ "${arg1}" = "restart" ]; then fun_clangcn fi if fun_check_run; then echo -n $"Stopping ${ProgramName}: " if [ -f /etc/rc.d/init.d/functions ]; then killproc -p $PID_FILE >/dev/null 2>&1 else if fun_check_run; then kill -9 $PID >/dev/null 2>&1 echo " [ok]" else echo " [FAILED]" RETVAL=1 fi fi RETVAL=$? [ $RETVAL -eq 0 ] rm -f $PID_FILE else echo "${ProgramName} is not running." fi } fun_restart(){ fun_stop fun_start } fun_status(){ fun_check_run case $? in 0) echo "$NAME (pid $PID) is running..." ;; 1|2) echo "$NAME is stopped" RET_VAL=1 ;; esac } checkos(){ if grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then OS=CentOS elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then OS=Debian elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then OS=Ubuntu else echo "Not support OS, Please reinstall OS and retry!" exit 1 fi } fun_config(){ if [ -s ${CONFIGFILE} ]; then vi ${CONFIGFILE} else echo "${ProgramName} configuration file not found!" fi } fun_set_ngrok_username(){ userName="" read -p "Please input UserName for Ngrok(e.g.:ZhangSan):" userName check_ngrok_username } fun_set_ngrok_subdomain(){ # Set ngrok pass subdomain="" ddns="" dns="" echo "Please input subdomain for Ngrok(e.g.:dns1 dns2 dns3 dns4 dns5):" read -p "(subdomain number max five:):" subdomain check_ngrok_subdomain } fun_set_ngrok_authId(){ strPass=`fun_randstr` echo "Please input the password (more than 8) of Ngrok authId:" read -p "(Default password: ${strPass}):" strPassword if [ "$strPassword" = "" ]; then strPassword=$strPass fi check_ngrok_authId } check_ngrok_username(){ # check ngrok userName if [ "$userName" = "" ]; then echo "Your input is empty,please input again..." fun_set_ngrok_username else echo "Your username: ${userName}" fun_set_ngrok_subdomain fi } check_ngrok_subdomain(){ # check ngrok subdomain if [ "$subdomain" = "" ]; then echo "Your input is empty, please input again." fun_set_ngrok_subdomain else fun_load_config ddns=(${subdomain}) if [ "$SingleUser" = "y" ] || [ "$SingleUser" = "1" ]; then [ -n "${ddns[0]}" ] && subdns=\"${ddns[0]}\" [ -n "${ddns[1]}" ] && subdns=\"${ddns[0]}\",\"${ddns[1]}\" [ -n "${ddns[2]}" ] && subdns=\"${ddns[0]}\",\"${ddns[1]}\",\"${ddns[2]}\" [ -n "${ddns[3]}" ] && subdns=\"${ddns[0]}\",\"${ddns[1]}\",\"${ddns[2]}\",\"${ddns[3]}\" [ -n "${ddns[4]}" ] && subdns=\"${ddns[0]}\",\"${ddns[1]}\",\"${ddns[2]}\",\"${ddns[3]}\",\"${ddns[4]}\" [ -n "${ddns[0]}" ] && FQDN=\"${ddns[0]}.${dns}\" [ -n "${ddns[1]}" ] && FQDN=\"${ddns[0]}.${dns}\",\"${ddns[1]}.${dns}\" [ -n "${ddns[2]}" ] && FQDN=\"${ddns[0]}.${dns}\",\"${ddns[1]}.${dns}\",\"${ddns[2]}.${dns}\" [ -n "${ddns[3]}" ] && FQDN=\"${ddns[0]}.${dns}\",\"${ddns[1]}.${dns}\",\"${ddns[2]}.${dns}\",\"${ddns[3]}.${dns}\" [ -n "${ddns[4]}" ] && FQDN=\"${ddns[0]}.${dns}\",\"${ddns[1]}.${dns}\",\"${ddns[2]}.${dns}\",\"${ddns[3]}.${dns}\",\"${ddns[4]}.${dns}\" else [ -n "${ddns[0]}" ] && subdns=\"${ddns[0]}.${userName}\" [ -n "${ddns[1]}" ] && subdns=\"${ddns[0]}.${userName}\",\"${ddns[1]}.${userName}\" [ -n "${ddns[2]}" ] && subdns=\"${ddns[0]}.${userName}\",\"${ddns[1]}.${userName}\",\"${ddns[2]}.${userName}\" [ -n "${ddns[3]}" ] && subdns=\"${ddns[0]}.${userName}\",\"${ddns[1]}.${userName}\",\"${ddns[2]}.${userName}\",\"${ddns[3]}.${userName}\" [ -n "${ddns[4]}" ] && subdns=\"${ddns[0]}.${userName}\",\"${ddns[1]}.${userName}\",\"${ddns[2]}.${userName}\",\"${ddns[3]}.${userName}\",\"${ddns[4]}.${userName}\" [ -n "${ddns[0]}" ] && FQDN=\"${ddns[0]}.${userName}.${dns}\" [ -n "${ddns[1]}" ] && FQDN=\"${ddns[0]}.${userName}.${dns}\",\"${ddns[1]}.${userName}.${dns}\" [ -n "${ddns[2]}" ] && FQDN=\"${ddns[0]}.${userName}.${dns}\",\"${ddns[1]}.${userName}.${dns}\",\"${ddns[2]}.${userName}.${dns}\" [ -n "${ddns[3]}" ] && FQDN=\"${ddns[0]}.${userName}.${dns}\",\"${ddns[1]}.${userName}.${dns}\",\"${ddns[2]}.${userName}.${dns}\",\"${ddns[3]}.${userName}.${dns}\" [ -n "${ddns[4]}" ] && FQDN=\"${ddns[0]}.${userName}.${dns}\",\"${ddns[1]}.${userName}.${dns}\",\"${ddns[2]}.${userName}.${dns}\",\"${ddns[3]}.${userName}.${dns}\",\"${ddns[4]}.${userName}.${dns}\" fi echo "Your subdomain: ${subdns}" fun_set_ngrok_authId fi } check_ngrok_authId(){ # check ngrok authId if [ "${strPassword}" = "" ]; then echo "Your input is empty, please input again..." fun_set_ngrok_authId else echo "Your authId: ${strPassword}" fun_adduser_command fi } fun_adduser_command(){ fun_load_config clear fun_clangcn echo curl -H \"Content-Type: application/json\" -H \"Auth:${pass}\" -X POST -d \''{'\"userId\":\"${strPassword}\",\"authId\":\"${userName}\",\"dns\":[${subdns}]'}'\' http://localhost:${manage_port}/adduser >${ProGramInstallPath}/.ngrok_adduser.sh chmod +x ${ProGramInstallPath}/.ngrok_adduser.sh . ${ProGramInstallPath}/.ngrok_adduser.sh rm -f ${ProGramInstallPath}/.ngrok_adduser.sh echo "" echo "User list :" curl -H "Content-Type: application/json" -H "Auth:${pass}" -X GET http://localhost:${manage_port}/info echo "=============================================================" echo "Server: ${dns}" echo "Server ${remote_port}" echo "userId: ${userName}" echo "authId: ${strPassword}" echo "Subdomain: ${subdns}" echo "Your FQDN: ${FQDN}" echo "=============================================================" } fun_adduser(){ if fun_check_run; then fun_load_config fun_set_ngrok_username else echo "${ProgramName} is not running." fi } fun_deluser(){ if [ -z "${1}" ]; then strWantdeluser="" fun_userlist echo "" read -p "Please input del username you want:" strWantdeluser if [ "${strWantdeluser}" = "" ]; then echo "Error: You must input username!!" exit 1 else deluser_Confirm_clang "${strWantdeluser}" fi else deluser_Confirm_clang "${1}" fi } deluser_Confirm_clang(){ if [ -z "${1}" ]; then echo "Error: You must input username!!" exit 1 else strDelUser="${1}" echo "You want del ${strDelUser}!" read -p "(if you want please input: y,Default [no]):" strConfirmDel case "$strConfirmDel" in y|Y|Yes|YES|yes|yES|yEs|YeS|yeS) echo "" strConfirmDel="y" ;; n|N|No|NO|no|nO) echo "" strConfirmDel="n" ;; *) echo "" strConfirmDel="n" esac if [ $strConfirmDel = "y" ]; then if [ -s "${ProGramInstallPath}/users/ng/ro/ngrok:${strDelUser}" ]; then rm -f ${ProGramInstallPath}/users/ng/ro/ngrok:${strDelUser} echo "Delete user ${strDelUser} ok! Restart ${NAME}..." fun_restart else echo "" echo "Error: user ${strDelUser} not found!" fi else echo "you cancel!" fi fi } fun_userlist(){ fun_clangcn echo "Ngrok user list:" ls ${ProGramInstallPath}/users/ng/ro/ |cut -d ':' -f 2 } fun_info(){ fun_clangcn if fun_check_run; then fun_load_config curl -H "Content-Type: application/json" -H "Auth:${pass}" -X GET http://localhost:${manage_port}/info else echo "${ProgramName} is not running." fi } arg1=$1 arg2=$2 [ -z ${arg1} ] case "${arg1}" in start|stop|restart|status|config|adduser|deluser|userlist|info) fun_${arg1} ${arg2} ;; *) fun_clangcn echo "Usage: $SCRIPTNAME {start|stop|restart|status|config|adduser|deluser|userlist|info}" RET_VAL=1 ;; esac exit $RET_VAL