core_messages.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. #!/bin/bash
  2. # LinuxGSM core_messages.sh module
  3. # Author: Daniel Gibbs
  4. # Contributors: https://linuxgsm.com/contrib
  5. # Website: https://linuxgsm.com
  6. # Description: Defines on-screen messages such as [ OK ] and how script logs look.
  7. moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
  8. # nl: new line: message is following by a new line.
  9. # eol: end of line: message is placed at the end of the current line.
  10. fn_ansi_loader() {
  11. # plain: stdout is not a terminal, output complete lines with no terminal control sequences.
  12. unset plainoutput plainpending
  13. if [ ! -t 1 ]; then
  14. plainoutput="1"
  15. fi
  16. # carriage return.
  17. creeol="\r"
  18. if [ -n "${plainoutput}" ]; then
  19. creeol=""
  20. elif [ "${ansi}" != "off" ]; then
  21. # echo colors
  22. default="\e[0m"
  23. black="\e[30m"
  24. red="\e[31m"
  25. lightred="\e[91m"
  26. green="\e[32m"
  27. lightgreen="\e[92m"
  28. yellow="\e[33m"
  29. lightyellow="\e[93m"
  30. blue="\e[34m"
  31. lightblue="\e[94m"
  32. magenta="\e[35m"
  33. lightmagenta="\e[95m"
  34. cyan="\e[36m"
  35. lightcyan="\e[96m"
  36. darkgrey="\e[90m"
  37. lightgrey="\e[37m"
  38. white="\e[97m"
  39. # erase to end of line.
  40. creeol+="\033[K"
  41. # text styles
  42. bold="\e[1m"
  43. dim="\e[2m"
  44. italic="\e[3m"
  45. underline="\e[4m"
  46. reverse="\e[7m"
  47. fi
  48. }
  49. # plain: print any held in-place message as its own line.
  50. fn_print_plain_flush() {
  51. if [ -n "${plainpending}" ]; then
  52. echo -e "${plainpending}"
  53. unset plainpending
  54. fi
  55. }
  56. fn_sleep_time() {
  57. sleep "0.1"
  58. }
  59. fn_sleep_time_05() {
  60. sleep "0.5"
  61. }
  62. fn_sleep_time_1() {
  63. sleep "1"
  64. }
  65. fn_sleep_time_5() {
  66. sleep "5"
  67. }
  68. fn_sleep_time_10() {
  69. sleep "10"
  70. }
  71. # Log display
  72. ########################
  73. ## Feb 28 14:56:58 ut99-server: Monitor:
  74. fn_script_log() {
  75. if [ -d "${lgsmlogdir}" ]; then
  76. if [ -n "${commandname}" ]; then
  77. echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: ${commandname}: ${1}" >> "${lgsmlog}"
  78. else
  79. echo -e "$(date '+%b %d %H:%M:%S.%3N') ${selfname}: ${1}" >> "${lgsmlog}"
  80. fi
  81. fi
  82. }
  83. ## Feb 28 14:56:58 ut99-server: Monitor: PASS:
  84. fn_script_log_pass() {
  85. fn_script_log "PASS: ${1}"
  86. exitcode=0
  87. }
  88. ## Feb 28 14:56:58 ut99-server: Monitor: FATAL:
  89. fn_script_log_fail() {
  90. fn_script_log "FAIL: ${1}"
  91. exitcode=1
  92. }
  93. ## Feb 28 14:56:58 ut99-server: Monitor: ERROR:
  94. fn_script_log_error() {
  95. fn_script_log "ERROR: ${1}"
  96. exitcode=2
  97. }
  98. ## Feb 28 14:56:58 ut99-server: Monitor: WARN:
  99. fn_script_log_warn() {
  100. fn_script_log "WARN: ${1}"
  101. exitcode=3
  102. }
  103. ## Feb 28 14:56:58 ut99-server: Monitor: INFO:
  104. fn_script_log_info() {
  105. fn_script_log "INFO: ${1}"
  106. }
  107. # On-Screen - Automated functions
  108. ##################################
  109. fn_print() {
  110. fn_print_plain_flush
  111. echo -en "$*${default}"
  112. }
  113. fn_print_nl() {
  114. fn_print_plain_flush
  115. echo -e "$*${default}"
  116. }
  117. # Helper function to print messages with a specific format and color
  118. # plain: in-place messages are held until replaced, completed by an eol message or flushed.
  119. fn_print_message() {
  120. local type="$1"
  121. local color="$2"
  122. local message="$3"
  123. local line
  124. if [ "${commandaction}" ]; then
  125. line="[${color} ${type} ${default}]${default} ${commandaction} ${selfname}: ${message}${default}"
  126. else
  127. line="[${color} ${type} ${default}]${default} ${message}${default}"
  128. fi
  129. if [ -n "${plainoutput}" ]; then
  130. plainpending="${line}"
  131. else
  132. echo -en "${bold}${creeol}${line}"
  133. fi
  134. fn_sleep_time
  135. }
  136. fn_print_message_nl() {
  137. local type="$1"
  138. local color="$2"
  139. local message="$3"
  140. unset plainpending
  141. if [ "${commandaction}" ]; then
  142. echo -e "${bold}${creeol}[${color} ${type} ${default}]${default} ${commandaction} ${selfname}: ${message}${default}"
  143. else
  144. echo -e "${bold}${creeol}[${color} ${type} ${default}]${default} ${message}${default}"
  145. fi
  146. fn_sleep_time
  147. }
  148. # Helper function to print eol messages with a specific color
  149. fn_print_eol() {
  150. local type="$1"
  151. local color="$2"
  152. if [ -n "${plainpending}" ]; then
  153. plainpending+=" ... ${type}"
  154. else
  155. echo -en " ... ${color}${type}${default}"
  156. fi
  157. }
  158. fn_print_eol_nl() {
  159. local type="$1"
  160. local color="$2"
  161. if [ -n "${plainpending}" ]; then
  162. echo -e "${plainpending} ... ${type}"
  163. unset plainpending
  164. else
  165. echo -e " ... ${color}${type}${default}"
  166. fi
  167. }
  168. # [ .... ]
  169. fn_print_dots() {
  170. fn_print_message "...." "${default}" "$*"
  171. fn_sleep_time_05
  172. }
  173. fn_print_dots_nl() {
  174. fn_print_message_nl "...." "${default}" "$*"
  175. fn_sleep_time_05
  176. }
  177. # [ OK ]
  178. fn_print_ok() {
  179. fn_print_message " OK " "${green}" "$*"
  180. }
  181. fn_print_ok_nl() {
  182. fn_print_message_nl " OK " "${green}" "$*"
  183. }
  184. # [ FAIL ]
  185. fn_print_fail() {
  186. fn_print_message "FAIL" "${red}" "$*"
  187. }
  188. fn_print_fail_nl() {
  189. fn_print_message_nl "FAIL" "${red}" "$*"
  190. }
  191. # [ ERROR ]
  192. fn_print_error() {
  193. fn_print_message "ERROR" "${red}" "$*"
  194. }
  195. fn_print_error_nl() {
  196. fn_print_message_nl "ERROR" "${red}" "$*"
  197. }
  198. # [ WARN ]
  199. fn_print_warn() {
  200. fn_print_message "WARN" "${lightyellow}" "$*"
  201. }
  202. fn_print_warn_nl() {
  203. fn_print_message_nl "WARN" "${lightyellow}" "$*"
  204. }
  205. # [ INFO ]
  206. fn_print_info() {
  207. fn_print_message "INFO" "${cyan}" "$*"
  208. }
  209. fn_print_info_nl() {
  210. fn_print_message_nl "INFO" "${cyan}" "$*"
  211. }
  212. # [ SKIP ]
  213. fn_print_skip() {
  214. fn_print_message "SKIP" "${cyan}" "$*"
  215. }
  216. fn_print_skip_nl() {
  217. fn_print_message_nl "SKIP" "${cyan}" "$*"
  218. }
  219. # [ START ]
  220. fn_print_start() {
  221. fn_print_message "START" "${lightgreen}" "$*"
  222. }
  223. fn_print_start_nl() {
  224. fn_print_message_nl "START" "${lightgreen}" "$*"
  225. }
  226. # On-Screen - Interactive messages
  227. ##################################
  228. # Separator is different for details.
  229. fn_messages_separator() {
  230. if [ "${commandname}" == "DETAILS" ]; then
  231. # Fall back to 80 columns when there is no terminal (e.g. cron or Docker); bash 5.3+ rejects an empty printf width.
  232. local columns="${COLUMNS:-$(tput cols 2> /dev/null)}"
  233. printf '%*s\n' "${columns:-80}" '' | tr ' ' =
  234. else
  235. echo -e "${bold}=================================${default}"
  236. fn_sleep_time
  237. fi
  238. }
  239. # No More Room in Hell Debug
  240. # =================================
  241. fn_print_header() {
  242. fn_print_plain_flush
  243. echo -e ""
  244. echo -e "${bold}${lightyellow}${gamename} ${commandaction}${default}"
  245. fn_messages_separator
  246. }
  247. # Success!
  248. fn_print_success() {
  249. echo -en "${green}Success!${default} $*${default}"
  250. fn_sleep_time
  251. }
  252. fn_print_success_nl() {
  253. echo -e "${green}Success!${default} $*${default}"
  254. fn_sleep_time
  255. }
  256. # Failure!
  257. fn_print_failure() {
  258. echo -en "${red}Failure!${default} $*${default}"
  259. fn_sleep_time
  260. }
  261. fn_print_failure_nl() {
  262. echo -e "${red}Failure!${default} $*${default}"
  263. fn_sleep_time
  264. }
  265. # Error!
  266. fn_print_error2() {
  267. echo -en "${red}Error!${default} $*${default}"
  268. fn_sleep_time
  269. }
  270. fn_print_error2_nl() {
  271. echo -e "${red}Error!${default} $*${default}"
  272. fn_sleep_time
  273. }
  274. # Warning!
  275. fn_print_warning() {
  276. echo -en "${lightyellow}Warning!${default} $*${default}"
  277. fn_sleep_time
  278. }
  279. fn_print_warning_nl() {
  280. echo -e "${lightyellow}Warning!${default} $*${default}"
  281. fn_sleep_time
  282. }
  283. # Information!
  284. fn_print_information() {
  285. echo -en "${cyan}Information!${default} $*${default}"
  286. fn_sleep_time
  287. }
  288. fn_print_information_nl() {
  289. echo -e "${cyan}Information!${default} $*${default}"
  290. fn_sleep_time
  291. }
  292. # Skip!
  293. fn_print_skip2() {
  294. echo -en "${cyan}Skip!${default} $*${default}"
  295. fn_sleep_time
  296. }
  297. fn_print_skip2_nl() {
  298. echo -e "${cyan}Skip!${default} $*${default}"
  299. fn_sleep_time
  300. }
  301. # Y/N Prompt
  302. fn_prompt_yn() {
  303. fn_print_plain_flush
  304. echo -e ""
  305. local prompt="$1"
  306. local initial="$2"
  307. if [ "${initial}" == "Y" ]; then
  308. prompt+=" [Y/n] "
  309. elif [ "${initial}" == "N" ]; then
  310. prompt+=" [y/N] "
  311. else
  312. prompt+=" [y/n] "
  313. fi
  314. while true; do
  315. if ! read -e -i "${initial}" -p "${prompt}" -r yn && [ -z "${yn}" ]; then
  316. echo -e ""
  317. fn_print_error_nl "Unable to read an answer: no input available"
  318. fn_script_log_error "Unable to read an answer to \"${1}\": no input available"
  319. # shellcheck disable=SC2034 # Used by core_exit.sh.
  320. exitcode=2
  321. core_exit.sh
  322. fi
  323. case "${yn}" in
  324. [Yy] | [Yy][Ee][Ss]) return 0 ;;
  325. [Nn] | [Nn][Oo]) return 1 ;;
  326. *) echo -e "Please answer yes or no." ;;
  327. esac
  328. done
  329. }
  330. # Prompt for message
  331. fn_prompt_message() {
  332. while true; do
  333. unset prompt
  334. local prompt="$1"
  335. if ! read -e -p "${prompt}" -r answer && [ -z "${answer}" ]; then
  336. return 1
  337. fi
  338. if fn_prompt_yn "Continue" Y; then
  339. break
  340. fi
  341. done
  342. echo "${answer}"
  343. }
  344. # On-Screen End of Line
  345. ##################################
  346. # YES
  347. fn_print_yes_eol() {
  348. fn_print_eol "YES" "${cyan}"
  349. fn_sleep_time
  350. }
  351. fn_print_yes_eol_nl() {
  352. fn_print_eol_nl "YES" "${cyan}"
  353. fn_sleep_time
  354. }
  355. # NO
  356. fn_print_no_eol() {
  357. fn_print_eol "NO" "${red}"
  358. fn_sleep_time
  359. }
  360. fn_print_no_eol_nl() {
  361. fn_print_eol_nl "NO" "${red}"
  362. fn_sleep_time
  363. }
  364. # OK
  365. fn_print_ok_eol() {
  366. fn_print_eol "OK" "${green}"
  367. fn_sleep_time
  368. }
  369. fn_print_ok_eol_nl() {
  370. fn_print_eol_nl "OK" "${green}"
  371. fn_sleep_time
  372. }
  373. # FAIL
  374. fn_print_fail_eol() {
  375. fn_print_eol "FAIL" "${red}"
  376. fn_sleep_time
  377. }
  378. fn_print_fail_eol_nl() {
  379. fn_print_eol_nl "FAIL" "${red}"
  380. fn_sleep_time
  381. }
  382. # ERROR
  383. fn_print_error_eol() {
  384. fn_print_eol "ERROR" "${red}"
  385. fn_sleep_time
  386. }
  387. fn_print_error_eol_nl() {
  388. fn_print_eol_nl "ERROR" "${red}"
  389. fn_sleep_time
  390. }
  391. # WAIT
  392. fn_print_wait_eol() {
  393. fn_print_eol "WAIT" "${cyan}"
  394. fn_sleep_time
  395. }
  396. fn_print_wait_eol_nl() {
  397. fn_print_eol_nl "WAIT" "${cyan}"
  398. fn_sleep_time
  399. }
  400. # WARN
  401. fn_print_warn_eol() {
  402. fn_print_eol "WARN" "${lightyellow}"
  403. fn_sleep_time
  404. }
  405. fn_print_warn_eol_nl() {
  406. fn_print_eol_nl "WARN" "${lightyellow}"
  407. fn_sleep_time
  408. }
  409. # INFO
  410. fn_print_info_eol() {
  411. fn_print_eol "INFO" "${cyan}"
  412. fn_sleep_time
  413. }
  414. fn_print_info_eol_nl() {
  415. fn_print_eol_nl "INFO" "${cyan}"
  416. fn_sleep_time
  417. }
  418. # QUERYING
  419. fn_print_querying_eol() {
  420. fn_print_eol "QUERYING" "${cyan}"
  421. fn_sleep_time_1
  422. }
  423. fn_print_querying_eol_nl() {
  424. fn_print_eol_nl "QUERYING" "${cyan}"
  425. fn_sleep_time_1
  426. }
  427. # CHECKING
  428. fn_print_checking_eol() {
  429. fn_print_eol "CHECKING" "${cyan}"
  430. fn_sleep_time_1
  431. }
  432. fn_print_checking_eol_nl() {
  433. fn_print_eol_nl "CHECKING" "${cyan}"
  434. fn_sleep_time_1
  435. }
  436. # DELAY
  437. fn_print_delay_eol() {
  438. fn_print_eol "DELAY" "${green}"
  439. fn_sleep_time_1
  440. }
  441. fn_print_delay_eol_nl() {
  442. fn_print_eol_nl "DELAY" "${green}"
  443. fn_sleep_time_1
  444. }
  445. # CANCELED
  446. fn_print_canceled_eol() {
  447. fn_print_eol "CANCELED" "${lightyellow}"
  448. fn_sleep_time_1
  449. }
  450. fn_print_canceled_eol_nl() {
  451. fn_print_eol_nl "CANCELED" "${lightyellow}"
  452. fn_sleep_time_1
  453. }
  454. # REMOVED
  455. fn_print_removed_eol() {
  456. fn_print_eol "REMOVED" "${red}"
  457. fn_sleep_time_1
  458. }
  459. fn_print_removed_eol_nl() {
  460. fn_print_eol_nl "REMOVED" "${red}"
  461. fn_sleep_time_1
  462. }
  463. # UPDATE
  464. fn_print_update_eol() {
  465. fn_print_eol "UPDATE" "${lightblue}"
  466. fn_sleep_time
  467. }
  468. fn_print_update_eol_nl() {
  469. fn_print_eol_nl "UPDATE" "${lightblue}"
  470. fn_sleep_time
  471. }
  472. # SKIP
  473. fn_print_skip_eol() {
  474. fn_print_eol "SKIP" "${cyan}"
  475. fn_sleep_time
  476. }
  477. fn_print_skip_eol_nl() {
  478. fn_print_eol_nl "SKIP" "${cyan}"
  479. fn_sleep_time
  480. }
  481. fn_print_ascii_logo() {
  482. echo -e ""
  483. echo -e " mdMMMMbm"
  484. echo -e " mMMMMMMMMMMm"
  485. echo -e " mMMMMMMMMMMMMm"
  486. echo -e " mMMMMMMMMMMMMMMm"
  487. echo -e " hMMMV^VMMV^VMMMh"
  488. echo -e " MMMMM MM MMMMM"
  489. echo -e " hMMs vv sMMh"
  490. echo -e " hMMM: :MMMh"
  491. echo -e " .hMMMh hMMMh."
  492. echo -e " -dMMMh ${lightgrey}__${default} hMMMd-"
  493. echo -e " :mMMMs ${lightgrey}||${default} sMMMm:"
  494. echo -e " :MMMM+ ${lightgrey}||${default} ${red}_${default} +NMMN:"
  495. echo -e " .mMMM+ ${lightgrey}========${default} +MMMm."
  496. echo -e " yMMMy ${darkgrey}##############${default} yMMMy"
  497. echo -e " mMMM: ${darkgrey}##############${default} :MMMm"
  498. echo -e " mMM ${lightyellow}nn${default} ${lightyellow}nn${default} ${lightyellow}nn${default} ${lightyellow}nn${default} MMm"
  499. echo -e " o ${lightyellow}nNNNNNNNn${default} ${lightyellow}nNNNNNNNn${default} o"
  500. echo -e " ${lightyellow}nNNNNNNNNNn${default} ${lightyellow}nNNNNNNNNNn${default}"
  501. echo -e " ${lightyellow}nNNNNNNNNNNN${default} ${lightyellow}NNNNNNNNNNNn${default}"
  502. echo -e " ${lightyellow}+NNNNNNNNN:${default} ${lightyellow}:NNNNNNNNN+${default}"
  503. echo -e " ${lightyellow}nNNNNNNN${default} /\ ${lightyellow}NNNNNNNn${default}"
  504. echo -e " ${lightyellow}nnnnn${default} db ${lightyellow}nnnnn${default}"
  505. echo -e ""
  506. echo -e "${lightyellow}888${default} ${lightyellow}d8b${default} ${default}.d8888b. .d8888b. 888b d888"
  507. echo -e "${lightyellow}888 Y8P ${default}d88P Y88b d88P Y88b 8888b d8888"
  508. echo -e "${lightyellow}888${default} ${default}888${default} 888 Y88b. 88888b.d88888"
  509. echo -e "${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}88888b.${default} ${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}888${default} 888 Y888b. 888Y88888P888"
  510. echo -e "${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}88b${default} ${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}Y8bd8P${default} 888 88888 Y88b. 888 Y888P 888"
  511. echo -e "${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}X88K${default} 888 888 888 888 Y8P 888"
  512. echo -e "${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}Y88b${default} ${lightyellow}88Y${default} ${lightyellow}.d8pq8b.${default} Y88b d88P Y88b d88P 888 * 888"
  513. echo -e "${lightyellow}LinuxGSM${default} ${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}888${default} ${lightyellow}Y8888Y${default} ${lightyellow}888${default} ${lightyellow}888${default} Y2012P88 Y8888P 888 888"
  514. echo -e ""
  515. }
  516. fn_print_restart_warning() {
  517. fn_print_warn "${selfname} will be restarted"
  518. fn_script_log_warn "${selfname} will be restarted"
  519. totalseconds=3
  520. for seconds in {3..1}; do
  521. fn_print_warn "${selfname} will be restarted: ${totalseconds}"
  522. totalseconds=$((totalseconds - 1))
  523. fn_sleep_time_1
  524. if [ "${seconds}" == "0" ]; then
  525. break
  526. fi
  527. done
  528. fn_print_warn_nl "${selfname} will be restarted"
  529. }
  530. # Functions below are used to ensure that logs and UI correctly reflect the command it is actually running.
  531. # Useful when a command has to call upon another command causing the other command to overwrite commandname variables
  532. # Used to remember the command that ran first.
  533. fn_firstcommand_set() {
  534. if [ -z "${firstcommandname}" ]; then
  535. firstcommandname="${commandname}"
  536. firstcommandaction="${commandaction}"
  537. fi
  538. }
  539. # Used to reset commandname variables to the command the script ran first.
  540. fn_firstcommand_reset() {
  541. commandname="${firstcommandname}"
  542. commandaction="${firstcommandaction}"
  543. }