Shell公共函数:/etc/init.d/functions详解
Contents
在学习Shell的时候看到很多脚本都会有. /etc/init.d/functions 这一句,在网上查询了此函数的作用,故收藏在博客中
functions这个脚本是给/etc/init.d里边的文件使用的。提供了一些基础的功能,看看里边究竟有些什么。首先会设置umask,path,还有语言环境,然后会设置success,failure,warning,normal几种情况下的字体颜色。下面再看看提供的重要方法:
checkpid:检查是否已存在pid,如果有一个存在,返回0(通过查看/proc目录)
daemon:启动某个服务。/etc/init.d目录部分脚本的start使用到这个
killproc:杀死某个进程。/etc/init.d目录部分脚本的stop使用到这个
pidfileofproc:寻找某个进程的pid
pidofproc:类似上面的,只是还查找了pidof命令
status:返回一个服务的状态
echo_success,echo_failure,echo_passed,echo_warning分别输出各类信息
success,failure,passed,warning分别记录日志并调用相应的方法
action:打印某个信息并执行给定的命令,它会根据命令执行的结果来调用 success,failure方法
strstr:判断$1是否含有$2
confirm:显示 “Start service $1 (Y)es/(N)o/©ontinue? [Y]“的提示信息,并返回选择结果
详细分析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# -*-Shell-script-*- # # functions This file contains functions to be used by most or all # 注释 :该脚本几乎被 /etc/init.d/ 下的所有脚本所调用,因为它包含了大量的 # shell scripts in the /etc/init.d directory. # 的基础函数。同时也被 /etc/rc.d/rc.sysinit ,例如 success、action、failure 等函数 # TEXTDOMAIN=initscripts # 设置 TEXTDOMAIN 变量 #某些系统使用LC_MESSAGES shell变量所指定的消息类型. 其他一些系统根据 shell变量TEXTDOMAIN的值来创建消息类型的名称, 可能还会加上后缀'.mo'. 如果 你使用TEXTDOMAIN变量, 你可能需要设置变量TEXTDOMAINDIR指向消息类型文件所 在的位置. 还有某些系统以这种形式两个变量都使用: TEXTDOMAINDIR/LC_MESSAGES /Lc_Messages/TEXTDOMAIN.mo. ######################################################################################################################## # Make sure umask is sane # 确保 root 用户的 umask 是正确的 022 (也就是 rwxr-xr-x) umask 022 # Set up a default search path. # 设置默认的 PATH 变量 PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin" # 默认为 /sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin export PATH # 导出为环境变量 # Get a sane screen width # 设置正确的屏幕宽度 [ -z "${COLUMNS:-}" ] && COLUMNS=80 # 如果 COLUMNS 变量的值为空,则设置为 80 (列) [ -z "${CONSOLETYPE:-}" ] && CONSOLETYPE="`/sbin/consoletype`" # 如果 CONSOLETYPE 为空则设置 CONSOLETYPE 为 /sbin/consoletype 命令返回的值 # 一般是 vt 或者 pty 、serial ####################################################################################################### if [ -f /etc/sysconfig/i18n -a -z "${NOLOCALE:-}" ] ; then # 如果存在 /etc/sysconfig/i18n 且 NOLOCALE 变量的值为空,则 . /etc/sysconfig/i18n # 执行 /etc/sysconfig/i18n 文件,取得 LANG 变量的值 if [ "$CONSOLETYPE" != "pty" ]; then # 如果当前 console 类型不是 pty(远程登录),而是 vt 或者 serial ,则 case "${LANG:-}" in # 根据 LANG 的值作出选择 ja_JP*|ko_KR*|zh_CN*|zh_TW*|bn_*|bd_*|pa_*|hi_*|ta_*|gu_*) # 如果 LANG 是 日文、中文简体、中文繁体、韩文等,则 export LC_MESSAGES=en_US # 把 LC_MESSAGES 设置为 en_US export LANG # 同时导出为环境变量 ;; *) export LANG # 如果是其他类型的语言,则直接导出 LANG ; ; esac else # 如果当前 consle 是 pty [ -n "$LC_MESSAGES" ] && export LC_MESSAGES # 且如果 LC_MESSAGES 不为空,则直接导出 LC_MESSAGES export LANG fi fi #######################*******************************################### |
case语句 :它能够把变量的内容与多个模板进行匹配,再根据成功匹配的模板去决定应该执行哪部分代码。
使用格式:
case 匹配母板 in
模板1 [ | 模板2 ] … ) 语句组 ;;
模板3 [ | 模板4 ] … ) 语句组 ;;
esac
case语句的匹配是从上往下地匹配顺序。因此,case语句编写的原则是从上往下,模板从特殊到普通。在C语言里,case语句中有default模板,而在shell程序设计中,可能将模板写成*,就可以完成相同的功能。
case语句的模板支持匹配
匹配以n开头的所有情况: n*
匹配yes的所有字母大小不同的情况: [yY][eE][sS]
但不支持{}匹配,因为模板可以使用 | 就可以达到目的。
例程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 |
#!/bin/sh echo "Please input "yes" or "no"" read var case "$var" in [yY][eE][sS] ) echo "Your input is YES" ;; [nN][oO] ) echo "Your input is YES" ;; * ) echo "Input Error!" ;; esac exit 0 ###################################################### ###################################################### # 下面是设置 success、failure、passed、warning 4种情况下的字体颜色的 # Read in our configuration if [ -z "${BOOTUP:-}" ]; then # 首先如果 BOOTUP 变量为空,则 if [ -f /etc/sysconfig/init ]; then # 如果存在 /etc/sysconfig/init 文件,执行 /etc/sysconfig/init 文件 . /etc/sysconfig/init else # 否则我们就手工设置 # This all seem confusing? Look in /etc/sysconfig/init, # or in /usr/doc/initscripts-*/sysconfig.txt BOOTUP=color # 第一设置 BOOTUP 变量,默认就是 color RES_COL=60 # 第二设置设置在屏幕的第几列输出后面的 "[ xxx ]" ,默认是第60列 MOVE_TO_COL="echo -en 33[${RES_COL}G" # MOVE_TO_COL 是用于打印 "OK" 或者 "FAILED" ,或者 "PASSED" ,或者 "WARNING" 之前的部分,不含 "[" SETCOLOR_SUCCESS="echo -en 33[1;32m" # SETCOLOR_SUCCESS 设置后面的字体都为绿色 SETCOLOR_FAILURE="echo -en 33[1;31m" # SETCOLOR_FAILURE 设置后面将要输出的字体都为红色 SETCOLOR_WARNING="echo -en 33[1;33m" # SETCOLOR_WARNING 设置后面将要输出的字体都为黄色 SETCOLOR_NORMAL="echo -en 33[0;39m" # SETCOLOR_NORMAL 设置后面输出的字体都为白色(默认) LOGLEVEL=1 fi if [ "$CONSOLETYPE" = "serial" ]; then # 如果是通过串口登录的,则全部取消彩色输出 BOOTUP=serial MOVE_TO_COL= SETCOLOR_SUCCESS= SETCOLOR_FAILURE= SETCOLOR_WARNING= SETCOLOR_NORMAL= fi fi ###################################################### ###################################################### if [ "${BOOTUP:-}" != "verbose" ]; then # 如果 BOOTUP 变量的值不为 verbose ,则 INITLOG_ARGS="-q" # 把 INITLOG_ARGS 的值设置为 -q (安静模式) else # 否则 INITLOG_ARGS= # 把 INITLOG_ARGS 的值请空 fi ################################################################################################# # Check if $pid (could be plural) are running # 下面定义一个函数 checkpid (),目的是检查 /proc 下是否存在指定的目录(例如 /proc/1/) checkpid() { # 如果有任意一个存在,则返回0; local i #局部变量定义 for i in $* ; do [ -d "/proc/$i" ] && return 0 done return 1 # 如果给出的参数全部不存在对应的目录,则返回1 } ##################################################################################################### # A function to start a program. # 下面定义最重要的一个函数,daemon 函数,它的作用是启动某项服务。/etc/init.d/ 下的脚本的 start 部分都会用到它 daemon() { # Test syntax. local gotbase= force= local base= user= nice= bg= pid= nicelevel=0 while [ "$1" != "${1##[-+]}" ]; do # daemon 函数本身可以指定多个选项,例如 --check <value> ,--check=<value> , case $1 in '') echo $"$0: Usage: daemon [+/-nicelevel] {program}" # 也可以指定 nice 值 return 1;; --check) base=$2 gotbase="yes" shift 2 ;; --check=?*) base=${1#--check=} gotbase="yes" shift ;; --user) # 也可以指定要以什么用户身份运行(--user <usr> , --user=<usr>) user=$2 shift 2 ;; --user=?*) user=${1#--user=} shift ;; --force) force="force" # --force 表示强制运行 shift ;; [-+][0-9]*) nice="nice -n $1" # 如果 daemon 的第一个参数是数字,则认为是 nice 值 shift ;; *) echo $"$0: Usage: daemon [+/-nicelevel] {program}" return 1;; esac done # Save basename. # basename 就是从服务器的二进制程序的 full path 中取出最后的部分 [ -z "$gotbase" ] && base=${1##*/} # See if it's already running. Look *only* at the pid file. # 检查该服务是否已经在运行。不过 daemon 函数只查看 pid 文件而已 if [ -f /var/run/${base}.pid ]; then # 如果 /var/run 下存在该服务的 pid 文件,则 local line p read line < /var/run/${base}.pid # 从该 pid 文件每次读取一行,送给变量 line 。注意 pid 文件可能有多行,且不一定都是数字 for p in $line ; do # 对于 line 变量的每个 word 进行检查 [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid $p" # 如果 p 全部是数字,且存在 /proc/$p/ 目录,则认为该数字是一个 pid ,把它加入到 pid 变量 done # 到最后 pid 变量的值可能是有多个由空格分隔的数字组成 fi [ -n "${pid:-}" -a -z "${force:-}" ] && return # 如果 pid 变量最终为空,则 force 变量为空(不强制启动),则返回 # make sure it doesn't core dump anywhere unless requested # 下面对该服务使用的资源作一些设置 ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 # ulimit 是控制由该 shell 启动的进程能够使用的资源,-S 是 soft control 的意思,-c 是指最大的 core # dump 文件大小,如果 DEAMON_COREFILE_LIMIT 为空,则默认为 0 # if they set NICELEVEL in /etc/sysconfig/foo, honor it # 如果存在 /etc/sysconfi/foo 文件,且其中有 NICELEVEL 变量则用它代替 daemon 后面的那个 nice 值 [ -n "$NICELEVEL" ] && nice="nice -n $NICELEVEL" # 注意,这里的 nice 赋值是用 nice -n <value> 的格式,因为 nice 本身可以启动命令,用这个格式较方便 # Echo daemon # 如果 BOOTUP 的值为 verbose ,则打印一个服务名 [ "${BOOTUP:-}" = "verbose" -a -z "$LSB" ] && echo -n " $base" # And start it up. # 下面是开始启动它了 if [ -z "$user" ]; then # 如果 user 变量为空,则默认使用 root 启动它 $nice initlog $INITLOG_ARGS -c "$*" # 执行 nice -n <nice_value> initlog -q -c "$*" else # 如果指定了用户,则 $nice initlog $INITLOG_ARGS -c "runuser -s /bin/bash - $user -c "$*"" # 执行 nice -n <nice_value> initlog -q -c "runuser -s /bin/bash - <user> -c "$*" fi [ "$?" -eq 0 ] && success $"$base startup" || failure $"$base startup" # 如果上面的命令成功,则显示一个绿色的 [ OK ] ,否则显示 [ FAILURE ] } ################################################################################################ # A function to stop a program. # 下面定义另外一个很重要的函数 killproc ,/etc/init.d/ 下面的脚本的 stop 部分都会用到它 killproc() { RC=0 # RC 是最终返回的值,初始化为 0 # Test syntax. if [ "$#" -eq 0 ]; then # killproc 函数的语法格式是 killproc <service> [<signal>] ,例如 killproc sm-client 9 echo $"Usage: killproc {program} [signal]" return 1 fi notset=0 # noset 是用于检查用户是否指定了 kill 要使用的信号 # check for second arg to be kill level if [ -n "$2" ]; then # 如果 $2 不为空,则表示用户有设定信号,则 killlevel=$2 # 把 $2 的值赋予 killlevel 变量 else # 否则 notset=1 # notset 变量的值为1,同时 killlevel 为 '-9' (KILL 信号) killlevel="-9" fi # 补充 :注意,并不是说用户没有指定信号地停止某项服务时,就会立即用 kill -9 这样的方式强制杀死,而是先用 TERM 信号,然后再用 KILL # Save basename. base=${1##*/} # basename 就是得出服务的名称 # Find pid. pid= # 把 pid 变量的值清空。注意,不是指 pid 变量的值等于下面脚本的执行结果,要看清楚 if [ -f /var/run/${base}.pid ]; then # 下面和上面的 daemon 函数一样找出 pid local line p read line < /var/run/${base}.pid for p in $line ; do [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid $p" done fi if [ -z "$pid" ]; then # 不过和 daemon 不同的是,一旦 pid 为空不会直接 return 而是尝试用 pid 命令再次查找 pid=`pidof -o $$ -o $PPID -o %PPID -x $1 || # -o 是用于忽略某个 pid ,-o $$ 是忽略当前 shell 的 pid、-o $PPID 是忽略 shell 的 pid pidof -o $$ -o $PPID -o %PPID -x $base` # -o %PPID 是忽略 pidof 命令的父进程,要查询的进程是 $1 (fullpath) 或者 $base fi # Kill it. if [ -n "${pid:-}" ] ; then # 如果 pid 的值最终不为空,则 [ "$BOOTUP" = "verbose" -a -z "$LSB" ] && echo -n "$base " # 且 BOOTUP 的值为 verbose ,且 LSB 变量不为空,则打印一个服务名 if [ "$notset" -eq "1" ] ; then # 如果 notset 变量不为1,表示用户没有指定信号,则 if checkpid $pid 2>&1; then # 调用 checkpid $pid 检查是否在 /proc/ 下存在进程目录,如果有 # TERM first, then KILL if not dead # 先尝试用 TERM 信息,不行再用 KILL 信号 kill -TERM $pid >/dev/null 2>&1 # 执行 kill -TERM $pid usleep 100000 # usleep 和 sleep 一样,不过单位是百万分之1秒。这里休眠1秒 if checkpid $pid && sleep 1 && # 如果 checkpid $pid 还是查到有 /proc/<pid>/ 目录存在,则表示还没有杀死,继续等待1秒 checkpid $pid && sleep 3 && # 如果1秒后用 checkpid 检查还是有,则再等待3秒; checkpid $pid ; then # 如果还是没有杀死,则用 KILL 信号 kill -KILL $pid >/dev/null 2>&1 # 执行 kill -KILL 杀死它 usleep 100000 # 等待1秒种 fi fi checkpid $pid # 再次检查 pid 目录 RC=$? # 并把结果返回给 RC ,这就算是 killproc 的最后状态了 [ "$RC" -eq 0 ] && failure $"$base shutdown" || success $"$base shutdown" # 如果 RC 的值为0,则表示kill -9 没有杀死了进程,则调用 failure 函数,否则调用 success RC=$((! $RC)) # use specified level only # 上面都是在没有指定信号的情况的,下面是用户指定了信号的。例如 restart)或者 reload)部分 else # 这个 else 是针对 if [ "$notset" -eq "1" ] 的 if checkpid $pid; then # 如果检查到进程存在,则 kill $killlevel $pid >/dev/null 2>&1 # 执行kill命令,但使用指定的信号 $killlevel RC=$? # 并把状态值返回给变量 RC [ "$RC" -eq 0 ] && success $"$base $killlevel" || failure $"$base $killlevel" # 如果 RC 为0则表示成功,调用 success;否则调用 failure 函数 fi fi else # 这个 else 是针对 if [ -n "${pid:-}" ] 的,也就是说没有 pid 文件,pidof 命令也没有找到 pid ,则 failure $"$base shutdown" # 调用 failure 函数,表示停止服务失败 RC=1 # 同时 RC 的值为1 fi # Remove pid file if any. # 根据具体情况可能需要删除 pid 文件 if [ "$notset" = "1" ]; then # 如果 notset 不为1 ,也就是用户没有指定信号的情况 rm -f /var/run/$base.pid # 自动删除 /var/run 下的 pid 文件 fi return $RC # 并把 RC 作为 exit status 返回 } # 补充 :自所以删除 pid 文件只针对 notset 为1 的情况,是因为 -HUP 信号(重读配置),并不杀死进程,所以不能删除它的 pid 文件 # 例如下面 : # ps -ef |grep xinetd root 2635 1 0 12:25 ? 00:00:00 xinetd -stayalive -pidfile /var/run/xinetd.pid # ./xinetd reload Reloading configuration: [ OK ] # ps -ef |grep xinetd root 2635 1 0 12:25 ? 00:00:00 xinetd -stayalive -pidfile /var/run/xinetd.pid root 3927 3412 0 16:43 pts/0 00:00:00 grep xinetd #可以看到 pid 在 reload 后并没有变 ################################################################################################## # A function to find the pid of a program. Looks *only* at the pidfile # 下面的 pidfileofproc 函数和 checkpid 类似,但不执行 pidof 命令,只查询 pid 文件 pidfileofproc() { local base=${1##*/} # Test syntax. if [ "$#" = 0 ] ; then echo $"Usage: pidfileofproc {program}" return 1 fi # First try "/var/run/*.pid" files if [ -f /var/run/$base.pid ] ; then local line p pid= read line < /var/run/$base.pid for p in $line ; do [ -z "${p//[0-9]/}" -a -d /proc/$p ] && pid="$pid $p" done if [ -n "$pid" ]; then echo $pid return 0 fi fi } ################################################################################################# # A function to find the pid of a program. # 下面的 pidofproc 函数和上面的 pidfileofproc 函数类似,但多了一步 pidof 命令 pidofproc() { base=${1##*/} # Test syntax. if [ "$#" = 0 ]; then echo $"Usage: pidofproc {program}" return 1 fi # First try "/var/run/*.pid" files if [ -f /var/run/$base.pid ]; then local line p pid= read line < /var/run/$base.pid for p in $line ; do [ -z "${p//[0-9]/}" -a -d /proc/$p ] && pid="$pid $p" done if [ -n "$pid" ]; then echo $pid return 0 fi fi pidof -o $$ -o $PPID -o %PPID -x $1 || pidof -o $$ -o $PPID -o %PPID -x $base } #################################################################################### status() { # 注释 :下面的 status 函数是判断服务的状态,总共有4种 local base=${1##*/} local pid # Test syntax. if [ "$#" = 0 ] ; then echo $"Usage: status {program}" return 1 fi # First try "pidof" # 同样是查找 pid 先。直接使用 pidof 命令 pid=`pidof -o $$ -o $PPID -o %PPID -x $1 || pidof -o $$ -o $PPID -o %PPID -x ${base}` if [ -n "$pid" ]; then # 如果 pid 变量的值不为空,则表示找到进程, echo $"${base} (pid $pid) is running..." # 则打印 "xxx (pid nnn) is running " , return 0 # 并返回 0 fi # Next try "/var/run/*.pid" files # 如果 pidof 命令没有找到,则尝试从 pid 文件找 if [ -f /var/run/${base}.pid ] ; then read pid < /var/run/${base}.pid if [ -n "$pid" ]; then # 如果 pidof 命令找不到,但从 pid 文件找到了 pid ,则 echo $"${base} dead but pid file exists" # 打印 "xxx dead but pid file exists", return 1 # 并返回 1 fi fi # See if /var/lock/subsys/${base} exists # 如果 pidof 命令和 pid 文件都没有找到 pid ,则 if [ -f /var/lock/subsys/${base} ]; then # 如果在 /var/lock/subsys 下存在对应的文件,则 echo $"${base} dead but subsys locked" # 打印 “xxxx dead but subsys locked”, return 2 # 并返回 2 fi echo $"${base} is stopped" # 如果 pidof 命令、pidf 文件都没有找到pid ,且没有别锁,则打印 “xxx is stopped” return 3 # 并返回3 } ########################################################################################### # 注释 :下面的 echo_xxx 函数就是真正在屏幕上打印 [ ok ] 、[ PASSED ]、[ FAILURE ]、[ WARNING ] 的部分了 echo_success() { # 下面是 echo_success 部分 [ "$BOOTUP" = "color" ] && $MOVE_TO_COL # 首先是打印 “[” 之前的空格 echo -n "[ " # 然后打印 "[" [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS # 设置字体为红色 echo -n $"OK" # 打印 OK [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL # 返回字体为白色 echo -n " ]" # 打印 "]" echo -ne "r" # 换行。 return 0 # 返回 0,其他一律返回 1 echo_failure() { [ "$BOOTUP" = "color" ] && $MOVE_TO_COL echo -n "[" [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE echo -n $"FAILED" [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL echo -n "]" echo -ne "r" return 1 } echo_passed() { [ "$BOOTUP" = "color" ] && $MOVE_TO_COL echo -n "[" [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING echo -n $"PASSED" [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL echo -n "]" echo -ne "r" return 1 } echo_warning() { [ "$BOOTUP" = "color" ] && $MOVE_TO_COL echo -n "[" [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING echo -n $"WARNING" [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL echo -n "]" echo -ne "r" return 1 } ################################################################################################## # Inform the graphical boot of our current state update_boot_stage() { if [ "$GRAPHICAL" = "yes" -a -x /usr/bin/rhgb-client ]; then /usr/bin/rhgb-client --update="$1" fi return 0 } ################################################################################################ # Log that something succeeded success() { # success 函数除了打印 [ xxx ] 之外,还会使用 initlog 记录信息 if [ -z "${IN_INITLOG:-}" ]; then initlog $INITLOG_ARGS -n $0 -s "$1" -e 1 # -n 是 --name 的意思,-s 是 --string ,-e 是 --event ,1 表示完全成功 else # silly hack to avoid EPIPE killing rc.sysinit trap "" SIGPIPE echo "$INITLOG_ARGS -n $0 -s "$1" -e 1" >&21 trap - SIGPIPE fi [ "$BOOTUP" != "verbose" -a -z "$LSB" ] && echo_success return 0 } # Log that something failed failure() { rc=$? if [ -z "${IN_INITLOG:-}" ]; then initlog $INITLOG_ARGS -n $0 -s "$1" -e 2 # failure 的话 --event 是 2 是失败 else trap "" SIGPIPE echo "$INITLOG_ARGS -n $0 -s "$1" -e 2" >&21 trap - SIGPIPE fi [ "$BOOTUP" != "verbose" -a -z "$LSB" ] && echo_failure [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --details=yes return $rc } # Log that something passed, but may have had errors. Useful for fsck passed() { rc=$? if [ -z "${IN_INITLOG:-}" ]; then initlog $INITLOG_ARGS -n $0 -s "$1" -e 1 # passed 的话 --event 还是1 else trap "" SIGPIPE echo "$INITLOG_ARGS -n $0 -s "$1" -e 1" >&21 trap - SIGPIPE fi [ "$BOOTUP" != "verbose" -a -z "$LSB" ] && echo_passed return $rc } # Log a warning warning() { rc=$? if [ -z "${IN_INITLOG:-}" ]; then initlog $INITLOG_ARGS -n $0 -s "$1" -e 1 # warning 的话 --event 也是 1 else trap "" SIGPIPE echo "$INITLOG_ARGS -n $0 -s "$1" -e 1" >&21 trap - SIGPIPE fi [ "$BOOTUP" != "verbose" -a -z "$LSB" ] && echo_warning return $rc } #################################################################################################### # Run some action. Log its output. # action 函数是另外一个最重要的函数,它的作用是打印某个提示信息并执行给定命令 tion() { STRING=$1 echo -n "$STRING " if [ "${RHGB_STARTED}" != "" -a -w /etc/rhgb/temp/rhgb-console ]; then echo -n "$STRING " > /etc/rhgb/temp/rhgb-console fi shift initlog $INITLOG_ARGS -c "$*" && success $"$STRING" || failure $"$STRING" rc=$? echo if [ "${RHGB_STARTED}" != "" -a -w /etc/rhgb/temp/rhgb-console ]; then if [ "$rc" = "0" ]; then echo_success > /etc/rhgb/temp/rhgb-console else echo_failed > /etc/rhgb/temp/rhgb-console [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --details=yes fi echo fi return $rc } ############################################################################################### # returns OK if $1 contains $2 # strstr 函数是判断 $1 字符串是否含有 $2 字符串,是则返回0,否则返回1 () { [ "${1#*$2*}" = "$1" ] && return 1 return 0 } ############################################################################################# # Confirm whether we really want to run this service # confirm 函数是用于交互式的启动服务 nfirm() { [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --details=yes while : ; do echo -n $"Start service $1 (Y)es/(N)o/(C)ontinue? [Y] " # 会打印一个提示信息 read answer if strstr $"yY" "$answer" || [ "$answer" = "" ] ; then # 如果 answer 变量是 y 或者 Y 则 return 0 # 返回 0(但未真正启动) elif strstr $"cC" "$answer" ; then # 如果 answer 是 c 或者 C ,则 rm -f /var/run/confirm # 删除 /var/run/confirm 文件 [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --details=no return 2 # 返回2 elif strstr $"nN" "$answer" ; then # 如果 answer 是 n 或者 N,则 return 1 # 直接返回1 fi done } |
原文:http://www.cnblogs.com/image-eye/archive/2011/10/26/2220405.html