linux sh : use local shell script library
发布日期:2021-06-30 22:17:03 浏览次数:2 分类:技术文章

本文共 16049 字,大约阅读时间需要 53 分钟。

前言

上一个实验,工程是一个500行的脚本。

已经感到维护性不好了。
假设工程的功能增加了,代码量增加到几千行以上,如何改善脚本工程的可维护性呢?
看了段书,说到可以采用引入本地脚本库。相当于c语言中的include头文件。
使用库包含后,做其他工程时,就有可以重用的代码库了。

重构了一下,按照功能和逻辑,将主脚本中的代码下拉到脚本库中,改造完成后,看着清爽多了。

实验

# !/bin/bash# @file main.sh# @brief wrap a shell script functin to check user exist, #   use array to pass output parameter, not use any global var# include other shell script. ./sh.const_define. ./sh.helper. ./sh.prog_version. ./sh.test_case. ./sh.file_opt_etc_passwd. ./sh.user_info# --------------------------------------------------------------------------------# do task# --------------------------------------------------------------------------------function func_do_task() {    # test user exist and have home dir    fuc_show_user_info "root"    # user not exist, but have home dir    fuc_show_user_info "dev"    # user not exist and have not home dir    fuc_show_user_info "user_not_exist"}# --------------------------------------------------------------------------------# main shell script# --------------------------------------------------------------------------------func_initfunc_show_titlefunc_show_prog_infofunc_show_os_info# func_test_casefunc_do_taskfunc_show_tailfunc_uinit
# !/bin/bash# @file sh.const_define# @brief define project's const valueIND_CHAR=-LINE10=${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}${IND_CHAR}LINE80=${LINE10}${LINE10}${LINE10}${LINE10}${LINE10}${LINE10}${LINE10}${LINE10}WALL_CHAR='|'# --------------------------------------------------------------------------------# global value# --------------------------------------------------------------------------------## err code define#G_ERR_CODE_BASE=0G_ERR_CODE_OK=$(echo "scale=4; $G_ERR_CODE_BASE + 0" | bc)G_ERR_CODE_ERR=$(echo "scale=4; $G_ERR_CODE_BASE + 1" | bc)G_ERR_CODE_USER_NOT_EXIST=$(echo "scale=4; $G_ERR_CODE_BASE + 2" | bc)G_ERR_CODE_USER_NOT_EXIST_BUT_HAVE_HOME_DIR=$(echo "scale=4; $G_ERR_CODE_BASE + 3" | bc)# row info below# games:x:5:60:games:/usr/games:/bin/sh# one row have 7 fields, indicate char is ':'# field 0 is username# field 5 is home dir#g_etc_passwd_row_field_index_user_name=0g_etc_passwd_row_field_index_home_dir=5
# !/bin/bash# @file sh.file_opt_etc_passwd# @brief function operate /etc/passwd# --------------------------------------------------------------------------------# @fn func_get_user_name_and_home_dir_for_one_row_from_etc_passwd# @brief get usrname and homedir from one row from /etc/passwd# @parameter IN, $1, row content# @parameter OUT, array ary_to_return, #   ary_to_return[0] = arysize, #   ary_to_return[1] is rc, #   ary_to_return[2] is username, #   ary_to_return[3] = home dir# @return G_ERR_CODE_OK or G_ERR_CODE_ERR# --------------------------------------------------------------------------------function func_get_user_name_and_home_dir_for_one_row_from_etc_passwd() {    local ary_to_return    local rc=$G_ERR_CODE_ERR    local str_user_name=""    local str_home_dir=""    local str_field=""    local IFS_org=""    local pos=0    local b_was_get_user_name=false    local b_was_get_home_dir=false    IFS_org=$IFS    IFS=$':'    for str_field in $1    do        if [ $pos -eq $g_etc_passwd_row_field_index_user_name ]        then            b_was_get_user_name=true            str_user_name=$str_field        elif [ $pos -eq $g_etc_passwd_row_field_index_home_dir ]        then            b_was_get_home_dir=true            str_home_dir=$str_field        fi        pos=$(echo "scale=4; $pos + 1" | bc) # pos++        if [ "$b_was_get_home_dir" = true ] && [ "$b_was_get_home_dir" = true ]        then            rc=$G_ERR_CODE_OK            break        fi    done    IFS=$IFS_org    # fill output parameter    ary_to_return[0]=3    ary_to_return[1]=$rc    ary_to_return[2]=$str_user_name    ary_to_return[3]=$str_home_dir    echo ${ary_to_return[*]} # this is all array content    return $rc}# --------------------------------------------------------------------------------# @fn func_is_user_exist# @brief is user exist# @parameter IN, username# @prarmeter OUT, ary_to_return#   ary_to_return[0] = ary size#   ary_to_return[1] = return code#   ary_to_return[2] = user name#   ary_to_return[3] = home dir# @return g_err_code_xx# --------------------------------------------------------------------------------function func_is_user_exist() {    # ! because need use echo pass output parameter, so don't echo other messages on function or sub function    local ary_to_return    local rc=$G_ERR_CODE_ERR    local str_user_name=""    local str_user_home=""    local str_user_name_rv=""    local IFS_org=""    local str_row_content=""    local str_user_home_rv=""    local rc_tmp_ary    local rc_tmp=0    # user name    str_user_name=$1    # user home     str_user_home="/home/${str_user_name}"    IFS_org=$IFS    IFS=$'\n'    for str_row_content in $(cat "/etc/passwd")    do        rc_tmp_ary=$(func_get_user_name_and_home_dir_for_one_row_from_etc_passwd $str_row_content)        # rc_tmp_ary = 4 0 speech-dispatcher /var/run/speech-dispatcher        rc_tmp=$?        str_user_name_rv=$(func_get_ary_by_index 2 $rc_tmp_ary)        str_user_home_rv=$(func_get_ary_by_index 3 $rc_tmp_ary)        if [ $rc_tmp -eq $G_ERR_CODE_ERR ]        then            continue        elif [ "$str_user_name" = "$str_user_name_rv" ]        then            # ok : on rc_tmp_ary, can get username and homedir            rc=$G_ERR_CODE_OK            break;        fi    done    IFS=$IFS_org    if [ $rc -eq $G_ERR_CODE_OK ]    then        # find user in /etc/passwd        # set rc, fill ary and echo ary, then to return        ary_to_return[0]=3 # parameter counter(3 = $G_ERR_CODE_OK + user_name + user_home_dir)        ary_to_return[1]=$rc # reture code        ary_to_return[2]=$str_user_name_rv # user name        ary_to_return[3]=$str_user_home_rv # user home dir        echo ${ary_to_return[*]} # this is all array content        return $rc    fi    # if user name not in /etc/passwd, try to find is the user have home dir ?    # before opt a file, please check is file exist. if file is dir, do check also    # do check can guard some error message on opt file    if ! [ -d $str_user_home ]    then        rc=$G_ERR_CODE_USER_NOT_EXIST        # fill output parameter        ary_to_return[0]=3        ary_to_return[1]=$rc        ary_to_return[2]=$str_user_name        ary_to_return[3]=""        echo ${ary_to_return[*]}        return $rc    fi    # ls -d xx # only list dir by give    str_user_name_rv=$str_user_name    str_user_home_rv=$(ls -d $str_user_home) # e.g. return /home/root    rc_tmp=$? #e.g. return 0, 1, or other int value    # if dir not exist, rc_tmp = 2    # rc_tmp is number, cmpare use -eq    if [ 0 -eq $rc_tmp ]    then        str_user_home_rv=$str_user_home        rc=${G_ERR_CODE_USER_NOT_EXIST_BUT_HAVE_HOME_DIR}    else        str_user_home_rv=""        rc=${G_ERR_CODE_USER_NOT_EXIST}    fi    # fill ary and echo ary, set rc to return    ary_to_return[0]=3     ary_to_return[1]=$rc     ary_to_return[2]=$str_user_name_rv    ary_to_return[3]=$str_user_home_rv    echo ${ary_to_return[*]} # this is all array content    return $rc}
# !/bin/bash# @file sh.helper# @brief helper function for other shell script# --------------------------------------------------------------------------------# init# --------------------------------------------------------------------------------function func_init() {    local i_index=0    clear    # print 25 empty lines for run result    for (( i_index=0; i_index < 25; i_index++ ))    do        echo    done}# --------------------------------------------------------------------------------# uinit# --------------------------------------------------------------------------------function func_uinit() {    exit 0}# --------------------------------------------------------------------------------# show tail# --------------------------------------------------------------------------------function func_show_tail() {    echo -e "${LINE80}"    echo -e -n "${WALL_CHAR}"    echo -e "\tEND"    echo -e "${LINE80}"}# --------------------------------------------------------------------------------# show os info# --------------------------------------------------------------------------------function func_show_os_info() {    local str_date=$(date +%Y_%m_%d_%H_%M_%S)    # show time    echo -e -n "${WALL_CHAR}"    echo -e "\t${str_date}"    # show shell    echo -e -n "${WALL_CHAR}"    echo -e "\t${SHELL}"    # show language    echo -e -n "${WALL_CHAR}"    echo -e "\t${LANG}"    # show user    echo -e -n "${WALL_CHAR}"    echo -e "\t${USER}"    echo -e "${LINE80}"}# --------------------------------------------------------------------------------# @fn func_show_ary()# @param IN array name# @param IN array self# --------------------------------------------------------------------------------function func_show_ary() {    local array_in=""    local ary_item=""    local i_index=0    local i_index_to_disp=0    array_in=$@    IFS_org=$IFS    IFS=$' '    for ary_item in $array_in    do        # skip $1, this is array name        if [ $i_index -ne 0 ]        then            echo "$1[$i_index_to_disp] = $ary_item"            i_index_to_disp=$(echo "scale=4; $i_index_to_disp + 1" | bc)        fi        i_index=$(echo "scale=4; $i_index + 1" | bc)    done    IFS=$IFS_org    echo}# --------------------------------------------------------------------------------# @fn func_get_ary_by_index()# @brief the all array is {index_obj, ary[0], ary[1], ary[2], ...}# @param IN array index, index base 0, if index is 0, return ary[0], not return index_obj# @param IN array self# @return ary[i]# --------------------------------------------------------------------------------function func_get_ary_by_index() {    # ! because need use echo pass output parameter, so don't echo other messages on function or sub function    local array_in=""    local ary_item=""    local i_index=0    local i_index_obj=$1    array_in=$@    i_index_obj=$(echo "scale=4; $i_index_obj + 1" | bc)    i_index=0    IFS_org=$IFS    IFS=$' '    for ary_item in $array_in    do        if [ $i_index -eq 0 ]        then            # $1 is the obj index            i_index_obj=$ary_item            i_index_obj=$(echo "scale=4; $i_index_obj + 1" | bc)            elif [ $i_index -eq $i_index_obj ]        then            echo "$ary_item"            break        fi        i_index=$(echo "scale=4; $i_index + 1" | bc)    done    IFS=$IFS_org    return 0}
# !/bin/bash# @file sh.prog_version# @brief show this prog version. ./sh.const_define# run time env is debian7.5PROG_NAME="check user exist"PROG_VER="1.0.0.5"PROG_TIME="2018-02-14 10:42"# --------------------------------------------------------------------------------# show title# --------------------------------------------------------------------------------function func_show_title() {    echo -e "${LINE80}"    echo -e -n "${WALL_CHAR}"    echo -e "\t@file\tmain.sh"    echo -e -n "${WALL_CHAR}"    echo -e "\t@brief\twrap a shell script functin to check user exist"    echo -e -n "${WALL_CHAR}"    echo -e "\t\tuse array to pass output parameter"    echo -e "\t\tnot use any global var"    echo -e "\t\tuse my local shell script lib"    echo -e "${LINE80}"}# --------------------------------------------------------------------------------# show prog info# --------------------------------------------------------------------------------function func_show_prog_info() {    # show prog name    echo -e -n "${WALL_CHAR}"    echo -e "\t${PROG_NAME}"    # show prog version    echo -e -n "${WALL_CHAR}"    echo -e "\t${PROG_VER}"    # show code modify time    echo -e -n "${WALL_CHAR}"    echo -e "\t${PROG_TIME}"    echo -e "${LINE80}"}
# !/bin/bash# @file sh.test_case# @brief test function for other shell script# --------------------------------------------------------------------------------# @fn func_case_gen_ary# @brief gen ary[4] to test# @prarmeter OUT, ary_to_return#   ary_to_return[0] = ary size#   ary_to_return[1] = return code#   ary_to_return[2] = user name#   ary_to_return[3] = home dir# @return g_err_code_xx# --------------------------------------------------------------------------------function func_case_gen_ary() {    # ! because need use echo pass output parameter, so don't echo other messages on function or sub function    local rc=$G_ERR_CODE_USER_NOT_EXIST_BUT_HAVE_HOME_DIR    local ary_to_return    ary_to_return[0]=3    ary_to_return[1]=$rc    ary_to_return[2]="user_name"    ary_to_return[3]="user_home_dir"    echo ${ary_to_return[*]} # this is all array content    return $rc}# --------------------------------------------------------------------------------# save some test case# --------------------------------------------------------------------------------function func_test_case() {    # test : gen ary    ary_to_return=$(func_case_gen_ary)    rc=$?    # test : show ary    func_show_ary "ary_to_return" $ary_to_return    # test : func_get_ary_by_index, index base 0    str_rv=$(func_get_ary_by_index 0 $ary_to_return)    echo "str_rv = $str_rv"    func_get_ary_by_index 1 $ary_to_return    func_get_ary_by_index 2 $ary_to_return    ary_element_3=$(func_get_ary_by_index 3 $ary_to_return)    echo "ary_to_return[3] = $ary_element_3"}
# !/bin/bash# @file sh.user_info# @brief show user info# --------------------------------------------------------------------------------# fuc_show_user_info# --------------------------------------------------------------------------------function fuc_show_user_info() {    local ary_to_return    local rc=0    local i_index=0    local ary_val=""    local str_user_name=""    local str_user_home=""    # $1 is user name    ary_to_return=$(func_is_user_exist $1)    rc=$?    # func_show_ary "ary_to_return" $ary_to_return    if [ $rc -eq $G_ERR_CODE_OK ]    then        str_user_name=$(func_get_ary_by_index 2 $ary_to_return)        str_user_home=$(func_get_ary_by_index 3 $ary_to_return)        echo "user [$str_user_name] exist, user home dir = [$str_user_home])"    elif [ $rc -eq $G_ERR_CODE_USER_NOT_EXIST_BUT_HAVE_HOME_DIR ]    then        str_user_name=$(func_get_ary_by_index 2 $ary_to_return)        str_user_home=$(func_get_ary_by_index 3 $ary_to_return)        echo "user [$str_user_name] not exist, but have home dir, user home dir = [$str_user_home]"    elif [ $rc -eq $G_ERR_CODE_USER_NOT_EXIST ]    then        str_user_name=$(func_get_ary_by_index 2 $ary_to_return)        echo "user [$str_user_name] not exist"    else        echo "unknow return code, please contact admin"    fi    echo}

2018_02_16

工程大了之后,库最好放在其他目录中,主工程和库目录分开。

试了一下,果真可以。代码是一样的,包含库时指定其他库的路径名称,用相对路径试了一下,是可以的。

如果库分的合理,需要改变库包含路径的就是主工程(如果工程不复杂的话).

如果包含同目录下的库,也可以写成 . ./sh.my_lib的形式

整理后的工程目录结构

这里写图片描述

root@debian750devmin:/home/dev# find .../.bash_history./test_case./test_case/sh.test_case./readme.txt./helper./helper/sh.helper./helper/sh.file_opt_etc_passwd./helper/sh.user_info./main.sh./common./common/sh.os_info./common/sh.const_define./common/sh.prog_version

包含库路径变化了的sh

# !/bin/bash# @file main.sh# @brief wrap a shell script functin to check user exist, #   use array to pass output parameter, not use any global var# include other shell script. ./common/sh.const_define. ./common/sh.prog_version. ./common/sh.os_info. ./helper/sh.helper. ./helper/sh.file_opt_etc_passwd. ./helper/sh.user_info. ./test_case/sh.test_case# --------------------------------------------------------------------------------# do task# --------------------------------------------------------------------------------function func_do_task() {    # test user exist and have home dir    fuc_show_user_info "root"    # user not exist, but have home dir    fuc_show_user_info "dev"    # user not exist and have not home dir    fuc_show_user_info "user_not_exist"}# --------------------------------------------------------------------------------# main shell script# --------------------------------------------------------------------------------func_initfunc_show_titlefunc_show_prog_infofunc_show_os_info# func_test_casefunc_do_taskfunc_show_tailfunc_uinit

转载地址:https://lostspeed.blog.csdn.net/article/details/79324753 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:linux sh : sed and awk's basic usage
下一篇:linux sh : user array as function's input or output parameter

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年04月13日 01时04分43秒