美文网首页
shell script 入门

shell script 入门

作者: 字字经心 | 来源:发表于2022-07-23 16:15 被阅读0次

    为什么学shell

    操作系统其实是一组软件,控制整个计算机硬件如cpu调度,内存、磁盘存储输入输出是操作系统的内核(Kernel)。通常这组软件是不允许被没有管理能力的终端用户随便使用的,但总是需要让用户操作系统的,用户可以通过壳程序(shell)来达到目的。壳程序是提供给用户去操作系统的一个接口,像ls、mkdir这些常用的命令都是封装好的独立应用程序,它们可以利用壳程序再通过内核去操作系统。

    linux 很多地方都利用了shell script,shell 在系统管理是很好的工具,服务的启动关闭就是通过它来控制的。所以学习shell 有助于弄清楚linux的来龙去脉,是进一步理解linux的方式。

    但是shell script 不擅长大量数值运算,它调用外部函数库耗cpu。linux 默认的shell 是bash,它规范了接口的语法。学习shell 可以参考

    1. 认识和学习bash
    2. 学习shell scripts

    shell 操作环境

    利用系统提供的命令如,ls/mkdir/rm/mv 等,或者通过./xx.sh 执行已写好的可执行脚本。必须先搞清楚系统查询执行这些命令的顺序,所以在当前目录执行脚本文件时要加 ./ 代表相对,否则报找不到文件错误

    1. 以相对/绝对路径运行命令,例如『 /bin/ls 』或『 ./ls 』;
    2. 由 alias 找到该命令来运行;
    3. 由 bash 内建的 (builtin) 命令来运行;
    4. 透过 $PATH 这个变量的顺序搜寻到的第一个命令来运行。

    我们一登入linux 进入shell 之后,能使用一堆有用的变量,这是因为系统有一些环境配置文件的存在。bash 在启动时直接就读取这些配置文件,以规划好bash 的操作环境。配置文件有分全体系统的配置文件以及用户个人偏好设置文件。

    • /etc/profile 系统整体的配置
    • ~/.bash_profile ~/.bash_login ~/.profile 属于使用者个人配置

    同时也必须理解login shell 和 non-login shell 的概念,因为通过这两种进入的bash 环境,读取配置文件的顺序不同。

    • login shell,取得bash 需要完整的登录流程,比如通过secureCRT ssh 方式得到的bash 环境。
    • non-login shell,取得bash 接口的方法不需要重复的登陆举动,比如你在原本的bash 环境再次下达bash 命令,没有输入账号密码,那第二个bash 子程序也是non-login shell。所以在写脚本命令前一般都会配置环境变量

    下面是这两种方式读取配置文件的顺序,图来自鸟哥书籍。实线是主线流程,虚线是被调用的配置文件。图中是login shell 完整顺序图,而non-login shell 只读 ~/.bashrc

    bash1.png

    简单 shell script

    下面是简单shell script 的格式,PATH 很重要

    #!/bin/bash
    # Program:
    #       This program is a easy shell script
    # History:
    # 2019/07/23    lics    First release
    PATH=/usr/local/php/bin:/usr/local/node/bin:/usr/local
    export PATH
    
    # 文件名
    date=$(date +%Y%m%d)
    file=${date}
    
    # file 加不加{}只是习惯问题
    touch "$file"
    

    shell script 运行区别

    • sh script 或者 ./script ,利用直接运行的方式运行script,该script 都会使用一个新的bash 环境来运行脚本内的命令。script 是指子程序的bash 内运行的!注意的是,在子程序的各项变量或者动作将会结束而不会回到父程序中。
    • source script ,在父程序中运行脚本,script 的各项动作都会在父程序中生效。所以我们修改了/etc/profile 里面的环境变量时,都会运行source /etc/profile 使其有效,否则要重新登入才行。
    • exec 方式

    bash 语法

    在了解shell 的作用,操作环境,运行方式之后,可以进一步学习bash的基本语法。比如

    • bash 变量
    • bash 通配符和特殊符号
      • ()代表中间为子shell 的起始和结束
    • 判断式,关于文件类型,文件权限,整数,字符串
    • shell script 的默认变量 0,1
      • $# :代表后接的参数『个数』,以上表为例这里显示为『 4 』;
      • @ :代表『 "1" "2" "3" "$4" 』之意
      • * :代表『 "1c2c3c$4" 』,其中 c 为分隔字节,默认为空白键
    • 条件判断式,if--then/case---esac/function
    • 回圈,while--do/for----do

    定时服务器脚本

    通过一些例子来熟悉shell script, 写一个定时同步服务器时间的 script

    1. 和网络时间同步
    # 安装ntpdate工具
    yum -y install ntp ntpdate
    
    # 设置系统时间与网络时间同步
    ntpdate cn.pool.ntp.org
    
    # 将系统时间写入硬件时间
    hwclock --systohc
    
    1. 定时同步,利用crontab 来执行定时脚本
    # 编辑crontab
    vim /etc/crontab
    
    # 添加定时任务,每6分钟同步一次
    */10 * * * * ntpdate -u ntp.api.bz && clock -w
    
    service crond reload
    

    自动连接mysql

    每次都要通过输入密码连接数据库,难免烦躁,可以把数据库密码放在每个文件中,然后写script 连接

    # 创建con_mysql脚本文件,密码在/data/save/mysql_root 内
    exec mysql -uroot -p$(cat /data/save/mysql_root) 
    
    # 把con_mysql 所在目录添置PATH,在任何目录执行
    con_mysql 
    

    数据自动入库

    假如现在有很多.sql 和txt 文件数据要录入数据库中,我们可以写一个只要提供数据库名、文件所在目录名就可以完成目的的shell script。运行方式 [script] db_name [sql所在目录绝对路径]

    #!/bin/bash
    database=$1
    backup_dir=$2
    
    if [ "$database" == "" -o "$backup_dir" == ""  ] ; then
      echo "eg:bash $0 db_name data_dir"
      exit
    fi
    
    mysql -uroot -p`cat /data/save/mysql_root` -e "CREATE DATABASE IF NOT EXISTS ${database};"
    cd ${backup_dir}
    SQL_LIST=$(ls ${backup_dir} | /bin/grep sql)
    for sql_file in ${SQL_LIST}; do
        mysql -uroot -p`cat /data/save/mysql_root` ${database} < ${sql_file}
    done
    mysqlimport --local -uroot -p`cat /data/save/mysql_root` ${database} *.txt
    

    script 更新项目版本

    在项目开发中,项目版本更新过程一般如下

    1. 本地环境完成,自测无误
    2. 将代码push github
    3. 在内测机器pull 项目,进行测试

    在我们push 仓库后,每次都要手动去更新内测机器的代码,难免烦躁。可以写一个可视化操作界面,只需点击一个按钮,利用shell script 来完成git pull 和更新到内测机器相应项目目录的步骤

    bash 常见用法

    在学习bash shell 脚本的过程中,如遇陌生语法可以在 学习bash学习shell script这里,利用CTRL+F 查找学习。

    1. awk 处理文件
    # 根据匹配规则[@=] 列分割文件内容,并且输出第一列数据
    $(echo ${NAME}|awk -F '[@=]' '{print $1}')
    
    1. 查看linux 命令是否存在
    # 将type composer的结果信息写到 垃圾桶黑洞装置/deb/null
    # 2> 代表将执行命令结果的错误信息 写到文件
    # &1 代表和前一个文件相同
    # || 如果左边命令不报错,则不执行右边
    type composer >/dev/null 2>&1 || {
                echo "require composer but it's not installed.  Aborting";
                exit;
            }
    
    1. cp 一系列目录
    NEED_UPDATE_FILE = 'www scripts update deps';
     /bin/cp -rf ${NEED_UPDATE_FILE} release;
    
    1. 删除目录下的部分文件
    # find release 目录下文件且文件名为 *.svn*匹配
    # xargs 代表 rm -rf 的命令参数
    find release -type d -name "*.svn*" | xargs rm -rf
    
    1. 代表一系列目录,且去除目录下部分目录
    # 生成文件名,date xxx 是函数调用 xxx 是传参
    Date=`date "+%Y-%m-%d-%H%M%S"`
    TAR_FILE=web.oa.$Date.tar.gz
    
    # 打包文件,www/upload 除外
    NEED_UPDATE_FILE = 'www scripts update deps';
    tar cfz $TAR_FILE ${NEED_UPDATE_FILE} --exclude=www/upload
    
    1. 执行远程命令
    # 连接远程机器,并执行命令
    ssh -p22 $PUBLISH_USER@$IP "sudo mkdir -p $SERVER_DIR"
    # $? 代表了执行命令的结果,0代表成功,127是失败
    if [ $? -gt 0 ] ; then
        echo "远程创建目录失败"
        exit
    else
        scp -P 22 $TAR_FILE $PUBLISH_USER@$IP:/data/tmp
    fi
    
    1. 执行远程一系列命令
    # 通过这种方式
    ssh -p22 $PUBLISH_USER@$IP "sudo mv /data/tmp/${TAR_FILE} ${SERVER_DIR};cd ${SERVER_DIR};xxx;xxx"
    

    欢迎大家给我留言,提建议,指出错误,一起讨论学习技术的感受!

    相关文章

      网友评论

          本文标题:shell script 入门

          本文链接:https://www.haomeiwen.com/subject/ylrsirtx.html