• Linux基础知识_Shell编程笔记


     以下是一些 常用功能 , 基于 centos 6.5 x64, 也有部分centos7 64 会有提示。

    # cp /etc/localtime /etc/localtime.org  
    # rm /etc/localtime  
    # ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime  
    
    #启用中文支持
    vim /etc/profile
    
    export LC_ALL="zh_CN.UTF-8"
    export LANG="zh_CN.UTF-8"
    export LC_CTYPE="zh_CN.UTF-8"
    # en_US.UTF-8 还原
    
    source /etc/profile 
    
    netstat -nltp #  查看进程及端口
    kill -9 ****  #  杀死指定PID的进程
    
    # 类似于 httpd / nginx 停止接受新连接,等当前连接停止,重载配置文件,重开日志文件,重启服务
    kill -USR1 pid   
    
    
    # 开机启动界面  ########################################
    vim /etc/inittab  # 6.5版本以下
    systemctl set-default graphical.target  # 7版本 设置图形界面启动
    systemctl set-default multi-user.target # 由图形界面模式更改为命令行模式
    ##################################
    
    useradd test
    passwd test
    su test # su是用来切换用户,但是之前的用户依然是登录状态.
        # su不加参数是默认切到root, 缺点是用户需要知道root密码.
    su - # 加了横线表示切换到root及根目录下.
    
    #### sudo  则是为普通用户临时提供root权限. 
    #### 当用户使用sudo命令时, 系统会寻找/etc/sudoers文件,判断该用户是否有执行sudo权限
    vim /etc/sudoers # 为新用户添加sudo权限. 这样test用户才可以使用sudo 或者直接使用visudo命令
    
        test  ALL=(ALL)    ALL
    ### 用户  主机=(谁的身份)   命令 
    
        hadoop master=NOPASSWD: /bin/ls, /bin/cat # 只允许hadoop用户在master上免密执行ls, cat命令.
    ### 实际环境中,管理员会给普通用户配置sudo权限.
    
    sudo在执行带有重定向符号时,需要 sh -c "" 引号括起完整命令:
    
    sudo sh -c "echo 11111 > /data/test.txt"
     
        
    userdel -r test
    vim /etc/passwd #可以查看系统中的所有用户 
        root:x:0:0:root:/root:/bin/bash
        # 用户名:密码x:用户id0:组id0:描述信息root:用户根目录/root/:用户登录后的shell
        # x 是表示此处为空;采用shadow passwd,影子密码在 /etc/shadow 文件
        
    
    # 命令别名定义
    alias drm="rm -rf"  # drm 代表了命令rm -rf
    unalias drm  # 删除别名
    alias  # 查看别名
    
    ls -lh  --time-style=+"%Y-%m-%d %H:%M:%S" # 设置显示文件时间戳
    
    ############################ network ###############################
    vim /etc/sysconfig/network-scripts/ifcfg-eth0 # centos7以后 ens33
        DEVICE="eth0"
        BOOTPROTO="static"
        HWADDR="00:0C:29:F5:05:8E"
        NM_CONTROLLED="yes"
        ONBOOT="yes"
        TYPE="Ethernet"
        IPADDR=192.168.112.10
        NETMASK=255.255.255.0
        GATEWAY=192.168.112.2
        DNS1=192.168.112.2
    ##可删除HWADDR,UUID
    service network restart  # 重启网络服务
    
    ##网卡更换后,可编辑 vim /etc/udev/rules.d/70-persistent-net.rules
    # 将最后一条末尾改为 eth0 ,其它的网卡信息删除后保存
    reboot      # 重启
    ifconfig    # 网络信息
    
    
    # CentOS7之后,如果网卡不能启动,出现“ journalctl -xe ”的提示时,执行之后有“Failed to start LSB: Bring up/down networking” 时,可尝试以下命令:
    systemctl stop NetworkManager
    systemctl disable NetworkManager # 关闭自带网络管理套件
    systemctl start network.service
    ifconfig # 如果正常则幸运解决
    ## 可参考:http://blog.sina.com.cn/s/blog_6253d0970102xg3o.html
    
    
    curl www.taobao.com     # 得到某 url 内容,顺便也可以看看是否显得出中文
    curl -I www.baidu.com   # 返回站点响应头 Server: Tengine 
    # 如果有代理,也可以看到 X-Cache: 信息
    
    
    netstat #网络端口监听 -a显示所有选项, -t仅显示TCP, -u仅显示UDP, -l仅列出有监听的.
    
    netstat -nltp # 查看有监听端口的进程
    
    netstat -an |grep 'ESTABLISHED' |grep -i '8080' |wc -l    # 8080的连接数
    
    netstat -an |grep 'ESTABLISHED' |grep -i '27017' |wc -l   # mongodb的连接数
    
    netstat -an |grep 'ESTABLISHED' |wc -l    # 总连接数
    
    #修改hosts和主机名
    # 修改/etc/hosts 以及/etc/sysconfig/network 文件, 分别设置不同的HOSTNAME
    vim /etc/hosts
    192.168.112.10 master
    192.168.112.11 slave1
    192.168.112.12 slave2
    
    hostname master
    vim /etc/sysconfig/network
    HOSTNAME=master
    
    
    ### CentOS7 以上,需要执行命令:
    hostnamectl set-hostname *** 
    
    
    ### 关闭防火墙
    service iptables stop  
    setenforce 0  
    chkconfig iptables off
    
    View Code

    常用命令与工具:

    ######################################### 资源 情况 ####################
    du -hs db  # 显示db文件夹总大小
    du -hs     # 显示当前目录大小 也可以加 --max-depth=1
    df -h      # disk info
    df -hT     # disk info with FileSystem
    df -h db   # 查看db文件夹所在分区的磁盘使用情况
    free       # Memory
    top        # 任务管理器
    #------------------------ top  -------------------------------------
    top -p [PID]         # 监控指定PID 
    top -p 765,767,768   # 监控指定的三个 
    top -u user          # 只显示user进程 
    top -c               # 显示详细进程信息
    
    P   # CPU百分比排序
    M   # 内存
    T   # 累积CPU时间 
    s   # 刷新间隔
    k   # 结束指定进程 
    
    
    
    cat /dev/null > create_data_prod_py.log  # 清空这个日志文件 > 是覆盖输出, >> 是追加输出 
    echo > a.log  # 清空日志
    
    ## 重定向  
    ## 0 (STDIN)   1 (STDOUT)   2 (STDERR) 
    date > a.txt # 是重写内容
    date >> a.txt # 是附加内容
    wall < /etc/issue.net  # 输入重定向,广播了某文件的内容 
    ls /temp 2> ls.err # 错误重定向,出错时写入文件  数字2代表错误输出 
    cp -R /usr /backup/usr.bak 2> /bak.error  # 备份出错时,保存记录
    
    write user # 向用户user 发送消息
    wall  # 向所有用户发送消息
    
    
    ### 管道 
    ll /etc | more # 将前一个命令的结果作为后一个命令的输入
    ll /etc | grep init # 查看/etc下的以init筛选后的结果 
    ll /etc | grep init | wc -l # 管道连用,查看上面的结果有多少行.
    
    
    ## 命令连接符 ;   &&    ||
    pwd ; ls ; date # 就是类似于编程语言中分号的作用,命令依次执行。
    ls && pwd  # 逻辑与,第一个命令成功,才会执行第二个命令。失败则不执行第二个。
    ls || pwd  # 逻辑或,第一个命令成功,不执行第二个。失败则执行第二个。
    
    
    ## 命令替换符 将后边命令的输出作为前边命令的参数
    ll `which java` # 找到java后,列出目录
    
    
    ## 如果要编译程序,通常需要安装依赖,可以一条命令多个组件.
    yum install gcc gcc-c++ automake autoconf libtool openssl-devel pcre-devel -y 
    ## 以下是python2.7运行MySQLdb模块时,可能用到的:
    yum install gcc gcc-c++ -y 
    yum -y install mysql-devel  
    yum install python-devel  
    pip install --upgrade pip
    pip install MySQL-python -i http://pypi.douban.com/simple --trusted-host pypi.douban.com 

    压缩解压:

    # tar gz xz 
    tar zcf a.tar.gz logs   # common compress
    tar Jcf a.tar.xz logs   # high compress
    tar zxf xxx.tar.gz      # extract
    tar Jxf xxx.tar.xz      # extract
    gzip -9 xxx.log gzip -d xxx.log.gz #
    zip yum install -y zip unzip zip -r a.zip logs/ unzip b.zip unzip -l b.zip # rar cd /opt/ wget https://www.rarlab.com/rar/rarlinux-x64-5.9.0.tar.gz tar zxf rarlinux-x64-5.9.0.tar.gz ln -s /opt/rar/rar /usr/bin/rar ln -s /opt/rar/unrar /usr/bin/unrar # 7z yum install p7zip p7zip-plugins 7z a a.7z logs # compress 7z x a.7z # extract

    定时任务:

    
    #################################  crontab  #################################
    
    # crontab:
    crontab -l #查看当前用户的crontab内容.
    crontab -r #删除定时任务配置,如果不指定用户,则删除当前用户的.
    crontab -e #编辑某个用户的crontab内容. 创建时也就先执行这个命令。
    #crontab格式
    #分 时 日 月 周 命令
    0 0 * * * /shell/upFile2HDFS.sh   #每天0点执行一次
    
    */1 * * * * date >> /test/date.txt #每分钟将时间写入文件
     
    30 21 * * * /usr/local/etc/rc.d/httpd restart #每天21:30执行一次命令
    
    20 0,4,8,12,16,20 * * * /data/test.sh   # 0:20, 4:20, ... 20:20 执行脚本
    
    0,30 18-23 * * 6,0 /usr/local/etc/rc.d/httpd restart #每个周六,周日的18点到23点,每隔30分钟
    
    
    # 不要忘记开启crond服务。
    yum -y install crontabs   # 安装
    service crond start       # 启动服务
    
    nohup python -u myscript.py >> a.log &  #  指定脚本在后台运行。 nohup ... &
    
    jobs -l       # 可查看nohup跑的进程 
    ps -ef        # 通过进程查看
    netstat -ntp  # 通过端口查看
    
    
    ## --------------------- 任务切换到后台运行 ----------------------------
    # 以 scp -r 复制文件为例,因为要输密码,所以不能直接 nohup ... &
    scp -r A005003/ 10.170.6.117:/data/mongobak  # 复制文件到远端
    # 输密码,开始传送:
    ctrl + z        # 暂停 出现jobs列表
    bg %1           # 根据jobs的列表的任务号
    jobs            # 是否Running 
    disown -h %1    # 忽略hup信号
    ps -ef |grep scp 
    logout
    
    #################################  建立每台电脑的互信关系  #################################
    ssh-keygen         # 创建.ssh目录 ,一路回车即可.
    ssh-copy-id slave1 # 复制公钥到目标主机或IP
    
    ssh root@slave1    # 测试登录 ssh root@slave2 都能成功,不用密码,则互信成功.
    
    

    修改yum源:

    #----------------------------------------------------------------------#
    # 修改yum源为aliyun 
    # 先备份:
      mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
    # 下载配置文件 注意 centos版本
      wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
      yum makecache  # 生成缓存

    # 163 网址
    wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo #
    ----------------------------------------------------------------------# lsb_release -a # 查看发行版本号 如果需要安装 yum -y install redhat-lsb uname -a # 查看内核版本 cat /etc/os-release # 查看OS发行版
    cat /etc/redhat-release # 具体版本 cat /etc/issue # 查看发行版 ulimit
    -a # 显示目前资源限制的设定 ulimit -n # 打开文件描述符的最大值 more /etc/*release # 更多信息 getconf LONG_BIT # 系统位数 uptime # 运行时间 load avg 为1m,5m,15m的CPU均值 last # 登录日志 w # 负载与用户连接情况 cat /proc/cpuinfo # 查看cpu核数 vmstat # 查看进程、cpu、memory、交换、io、系统 last reboot # 第一行是上次重启时间 who -b # 上次重启时间 # 参考: https://www.cnblogs.com/zhangmingcheng/p/6438994.html

    设置时区时间相关

    date -s "2018-01-01 14:22:33" # 修改时间 参数后面加字符串
    clock -w # 写入硬件时钟
    date -R #显示时区
    tzselect #时区向导
    # 其实不考虑各个发行版的差异化, 从更底层出发的话, 修改时间时区比想象中要简单:
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime #修改时区

    # centos 7
    sudo timedatectl --help    # 系统时间控制台
    sudo timedatectl         # 显示时间信息
    sudo timedatectl set-time 15:22:22 # 设置时间
    sudo timedatectl set-time "2020-05-02 09:32:50" # 包括日期时间
    yum install ntp # 安装ntp服务
    ntpdate pool.ntp.org  # ntp对时
    chkconfig ntpd on
    /etc/init.d/ntpd start  # centos7 改到了/sbin/ntpd
    clock -w # 写入硬件时钟
    
    vim /etc/rc.d/rc.local # 可设置开机启动项目 并且要给此文件加可执行权限 已逐渐弃用,官方建议使用systemd  
    #例如,在最后加上 /etc/init.d/mysqld start则可以启动mysqld
    # centos7 若没有ifconfig,安装网络工具 ip addr yum -y install net-tools

    # centos7 可以使用以下命令,安装大多数开发工具及依赖
    yum groups info "Development Tools" # 查看
    yum groups install "Development Tools" # 安装
    # 此外,还有部分yum命令:
    yum list installed # 查看已安装的包
    yum list installed |grep docker # 查找是否安装docker

    yum remove -y *gnome* # 删除所有包含gnome的包及其依赖
    yum remove gnome-shell-3.26.2-5.el7.x86_64 # 单独删除某个包
    yum install epel-release # 使用 epel 库,这个库带有很多第三方软件 如 nginx wget https://mirrors.aliyun.com/epel/7/x86_64/Packages/e/epel-release-7-12.noarch.rpm # 也可以手动下载国内的epel源,然后安装 rpm -Uvh epel-release-7-12.noarch.rpm
    yum update          # 全部更新
    yum update epel-release # 只更新指定包
    yum install nginx       # 安装 nginx
    # 日期时间运算: echo $(date +"%F %T.%N" | cut -b 1-23) # 显示成常用log格式, 2020-07-23 07:58:03.116 echo $(date -d -10day +"%Y%m%d") # 显示10天前日期 20200713 单位可以是 year, month, day, week echo $(date -d -10min +"%F %T.%N" | cut -b 1-23) # 显示10分钟之前, 单位可以是 hour,min,sec, 可以加减 # %F 相当于 %Y-%m-%d , 而 %T 相当于 %H:%M:%S (24小时格式) %N是纳秒

    rpm 命令:

    rpm -qa |grep erlang      # 查找已安装的 erlang 相关软件
    rpm -Uvh rabbitmq-server     # U 如果有旧版则升级安装
    rpm -e --nodeps erlang-stdlib-R16B-03.18.el7.x86_64  # 卸载 忽略依赖,软件包
    

     history命令:

    -c:清除命令历史;
    -d:offset:删除指定命令历史;
    -r:从文件读取目录历史至历史列表中;
    -w:把历史列表中的命令追加至历史文件中 ~/.bash_history 
    
    history 20  显示最近的20条命令;
    !542  执行第542条命令
    
    # 添加环境变量:
    export HISTCONTROL=ignoreboth    # 忽略空格开头忽略重复命令
    export HISTTIMEFORMAT="%F %T "   # 命令带日期时间
    # 查找命令
    find / -name tomcat  # 找tomcat
    
    # 按常人理解的日期格式
    ls -lh  --time-style=+"%Y-%m-%d %H:%M:%S" 
    
    # 显示所有全局变量
    export 

    # shell多行注释
    :<<!
    被注释掉的内容
    !d


    cp -rf . /opt/apps/screen-frontend/dist/ # cp表示调用原生cp命令,-rf 表示递归处理及强制覆盖不提示 . 当前目录

    Vim的操作:

    ############# vim ###########################################
    命令模式下:
    1)把光标移动到要复制的行上,按yy (复制当前行) 
    2)把光标移动到要复制的位置 ,按p (粘贴到指定行)
    3)把光标移动到要复制的位置 ,按dd(删除当前行)
    
    移动光标: hjkl 左下上右
    ctrl+u:到文件头
    ctrl+d:到文件尾
    shift+h:到屏幕第一行,shift+m:到屏幕中间,shift+l:到最后一行, shift+zz 保存退出
    :n 到第n 行
    ^ 到行首,$ 到行尾 (这两个与正则一样)
    
    查找并高亮: /name 查找 name   n下一个,N上一个
    替换  :%s/原/   # 这是全部替换
    取消高亮: :noh :r
    ! pwd # 执行这个shell并将结果插入到当前行的下一行。 撤销更改:u:取消更改 插入:a从光标后,i从光标前,o从光标下一行

    :set ff      # 查看当前文本的模式类型,dos,unix
    :set ff=dos  # 设置为dos模式, 也可用 sed -i 's/$/ /'?
    :set ff=unix # 设置为unix模式,也可用 sed -i 's/.$//g'

    :set fileencoding  # 查看现在文本的编码
    :set fenc=utf8     # 转换当前编码为utf8 cp936, gb18030 ...

    列操作,比如每行开头加注释
    ESC, Ctrl + v 进入visual
    数字5,再下箭头,即可向下选中5行。
    shift + i 插入,# 再按2次ESC,即可在所有选中行前插入#
    按 d 即删除选中的部分

    # Vim批量注释
    ctrl+v 列编辑模式,上下移动光标,开头标记起来,按大写I(shift+i),插入注释符,比如"//",再Esc,就会全部注释
    # 批量去掉注释
    ctrl+v 列编辑模式,先上下,横向选中列的个数(如"//"注释符号,需要选中两列),然后按d, 就会删除注释符号
    
    ##配置文件 vim /etc/vimrc
    set nu   # 行号
    set ts=4 # tab距离4空格
    set et   # tab转换为真正的空格
    
    # modeline 相当于文件格式配置
    # vim:et:ts=4:sw=4:
    ############# vim  end #########################################

    挂载硬盘与分区 

    # 先在虚拟机中添加硬盘,比如3T大小,不用关机,Centos7 可直接检测到
    
    fdisk -l
    # 可以看到 Disk /dev/vdc: 3221.2GB   vdc 表示这是第3块盘了。
    # 挂载使用以下两种方式均可:
    
    #------------------------方式一: 整盘格式化,直接挂载 -------------------------
    mkfs.xfs /dev/vdc 
    # 直接格式化整盘,没有分区。注:fdisk 默认分区最大2T
    # ext4 文件系统逐渐老去,未来 xfs 将会取代。
    
    mkdir /E
    mount /dev/vdc /E
    # 挂载到 /E
    
    df -h 
    # Filesystem               Size  Used Avail Use% Mounted on
    # /dev/vdc                 2.9T  89M  2.8T  1%   /E
    # 写入文件试试。
    
    # 需要系统启动时自动挂载,则 vi /etc/fstab 添加一行:
    /dev/vdc   /E      xfs    defaults      1               2
    # 磁盘    挂载点  文件系统  选项   0忽略/1允许dump  fsck检查顺序0不检
    
    # umount /E 不用时可以卸载
    
    #------------------------ 方式二: 先分区再挂载 ---------------------------------
    # 开始分区
    fdisk /dev/vdc 
    m  # 帮助
    g  # 开始创建GPT分区表(因为vdc大于2T,所以必须GPT)
    n  # 开始创建分区,1号,然后一路默认回车。
    t # 改变分区类型
    L # 找到 Linux LVM 序号
    31 # 这个序号对应 Linux LVM ,每台机器可能不同,以实际为准。
    w # 保存 fdisk -l # 再次查看,得到以下信息: Disk /dev/vdc: 3221.2 GB, 3221225472000 bytes, 6291456000 sectors Disk label type: gpt Disk identifier: 2A96EF32-3BDB-4EAB-B7DB-113278422354 # Start End Size Type Name 1 2048 6291455966 3T Linux filesyste mkfs.xfs -f /dev/vdc1 # 格式化为XFS,等待数秒完成 mkdir /E mount /dev/vdc1 /E df -h # Filesystem Size Used Avail Use% Mounted on # /dev/vdc1 3.0T 33M 3.0T 1% /E # /dev/vdb 7.8T 1.8T 5.7T 24% /data # 需要系统启动时自动挂载,则 vi /etc/fstab 添加一行: /dev/vdc1 /E xfs defaults 1 2 # 磁盘 挂载点 文件系统 选项 0忽略/1允许dump fsck检查顺序0不检 # umount /E 不用时可以卸载

    调整挂载点 /home的容量到根 /

    df -h       
    # 发现/dev/mapper/centos-root 所剩空间很少,而 /dev/mapper/centos-home 有size 42G 
        
    sudo tar zcf /run/home.tar.gz /home # 打包home到run下,因为run有足够的空间可以暂存
    
    yum install -y psmisc   # 安装fuser
    sudo fuser -km /home    # 结束 home相关进程
    
    yum install -y lsof     # 也可使用 lsof |grep /home/ 来查看占用home的进程,然后kill
    
    sudo umount /home       # 卸载
    sudo lvremove /dev/mapper/centos-home           # 移除lv分区
    sudo lvextend -L +30G /dev/mapper/centos-root   # 增加root 30G
    sudo xfs_growfs /dev/mapper/centos-root         # 扩大文件系统
    
    sudo lvcreate -L 11G -n/dev/mapper/centos-home  # 只剩11G,都给home, 如果超过可用大小,会有提示。
    sudo mkfs.xfs  /dev/mapper/centos-home          # 格式化
    sudo mount /dev/mapper/centos-home              # 挂载
    sudo tar zxf /run/home.tar.gz -C /              # 恢复home

    如果是VM之类的扩展了物理硬盘,则centos需要在系统中操作:

    df -h     # 查看当前容量
    fdisk -l  # 查看哪个分区容量明显多于上面显示的容量
    
    fdisk /dev/sda   # 下面是依次输入
    m
    n    # 新建
    p    # 数值默认
    t     # 改变system为 LVM
    8e
    p    # 显示分区表 ( 假设新分区为 sda3 )
    w    # 保存
    
    reboot   # 需要重启
    
    lvm   # 进入LVM
     pvcreate /dev/sda3
     pvdisplay     # 显示卷信息 (假设要给sda2扩展容量,sda2的 VG name 是 centos
     vgextend centos /dev/sda3  # 加入和 sda2同一个VG组
     exit
    
    lvextend -L +12G /dev/mapper/centos-root  # 也可以按M单位增加也可执行多次,只要pvdisplay中还有 Free PE
    
    xfs_growfs /dev/mapper/centos-root   # 执行容量增长

    挂载windows的共享:

    mount -t cifs -ro username=admin,password=123456 //192.168.1.12/share /opt/share
    • username,password 是windows登录用户名密码
    • //192.168.1.12/share 是windows的共享文件夹
    • /share是希望Centos7将要挂载到的地方,可任意位置

      开机启动就挂载文件夹,在/etc/fstab文件中添加

    //192.168.1.12/share /share cifs username=admin,password=123456   0 0

    知识点参考:http://www.jinbuguo.com/man/mount.cifs.html

    如果失败,可能缺少组件。 yum install cifs-utils

    shell编程一定要注意,变量名和=之间不能有空格; 原生bash不支持简单数学运算,必须借助expr表达式工具等。 

    对于习惯其它开发语言的人来说,这个shell的格式很容易让人出错。

    想要掌握并记忆,还是要多写几次练习。

    #!/bin/bash 
    
    # 上面第一行是解释器   bash shell是Linux默认的免费的
    ## 通常会在第二行开始写脚本说明,作者,时间等。
    
    #chmod +x hello.sh # 给全部用户加上执行权限 脚本的执行需要有x权限
    #chmod u+x hello.sh #给当前用户加上执行权限 
    chmod 755 hello.sh  # 所有者 所属组 其他人。 7 = 4+2+1 表示拥有"读/写/执行"的权限
    
    cat /etc/shells #查看当前系统中的所有shell
    
    ## 执行脚本时 -x 参数可以看到具体拭执行过程
    
    ###################### shell 第一个例子:查看系统概况 ###################
    # echo -e 参数可以识别字符串中的转义字符
    #
    !/bin/sh # auto mail for sys info /bin/date +%F >> /tmp/sysinfo # 日期信息写入临时文件 echo "disk info:" >> /tmp/sysinfo /bin/df -h >> /tmp/sysinfo # 真正的disk信息 echo >> /tmp/sysinfo # 显示空行 echo "online users:" >> /tmp/sysinfo /usr/bin/who | /bin/grep -v root >> /tmp/sysinfo # 列出所有用户,不看root echo >> /tmp/sysinfo echo "memory info:" >> /tmp/sysinfo /usr/bin/free -m >> /tmp/sysinfo echo >> /tmp/sysinfo # write root /usr/bin/write root < /tmp/sysinfo && /bin/rm /tmp/sysinfo #信息发给root,然后删除 # crontab -e # 0 9 * * 1-5 script ###################### end 第一个例子 ################################## ###################### 变量 #################################### name="abcde" # 变量名和=之间不能有空格 export a='aaaaa' #声明为全局变量 # 在a.sh中调用b.sh 写上source则表示在同一个进程中执行. source ./b.sh . ./b.sh # 也可用. 来代替source echo "${name}s a bcd." # 大括号确定了变量的边界 注意需要使用双引号;单引号则不会识别变量 readonly aa=1234 # 只读变量aa,不可修改 unset a ## 删除变量 ##局部变量仅能在当前会话中访问. set ##set命令可以查看环境变量 ###################### 变量参数 #################################### #脚本内获取参数的格式为$n n代表数字, 1第一个参数,2是第二个参数,以此类推... #特殊符号: $#参数个数, $*所有参数为一个字符串, $$脚本运行的当前进程ID, $!后台运行的最后一个进程ID, $@ 与$*相同,但是使用时加引号,在引号中返回每个参数. $? 显示最后命令状态, $*与$@区别: 是否被双引号包含. #!/bin/bash echo "脚本名称: $0"; echo "第一个参数: $1"; echo "参数个数: $#"; echo "传递的参数作为一个字符串: $*"; echo "进程号: $$"; echo "结束: $?"; ###################### 第二个例子: 备份 ################################## # $1 利用了位置参数. 例如执行 sh autobak.sh /usr 时,$1 即表示/usr #!/bin/bash # backup files by date DATE=`/bin/date +%Y%m%d` /bin/tar -cf /backup/$1.$DATE.tar $1 > /dev/null 2>> /backup/$1.bak.log /bin/gzip /backup/$1.$DATE.tar if [ $? -eq 0 ] then echo "$1 $DATE backup successful" >> /backup/$1.bak.log else echo "ERROR: failure $1 $DATE backup!" >> /backup/$1.bak.log fi # crontab -e # 0 3 * * 2,5 script ###################### 第二个例子: 备份 ################################## ################################ shell 运算符############################## # 原生bash不支持简单数学运算,可借助expr表达式工具以及``符号 ,完成求值. # 其实``叫命令替换符 val=`expr 2+3` #输出2+3 val=`expr 2 + 3` #输出5 val=`expr 2 * 3` #输出6 乘法要转义 val=`expr 2 / 3` #除法 val=`expr 2 % 3` #取模 #也可以用$(())或$[] 进行算术运算 #!/bin/bash count=1 ((count++)) echo $count a=$((1+2)) b=$[3+4] echo $a $b # 关系运算符 简称: -eq等于, -nq不等于, -gt大于, -lt小于, -ge大于等于, -le小于等于 # 关系运算符只支持数据,不支持字符串,除非是数字形字符串 #!/bin/bash a=10 b=20 if [ $a -eq $b ] then echo "$a -eq $b : a等于b" else echo "$a -nq $b : a不等于b" fi if [ 1 -lt 5 ]; then echo OK; else echo notok; fi ##单行写法. # 布尔运算符 -a且 -o或 只需单层方括号 if [ $a -lt 100 -a $b -gt 15 ] then echo "$a 小于100且 $b 大于15 : 返回true" else echo "$a 不小于100或 $b 不大于15 : 返回false" fi # 逻辑运算符 && 及|| 需要双层方括号 if [[ $a -lt 100 || $b -gt 100 ]] then echo "返回true" else echo "返回false" fi # 字符串运算符 #!/bin/bash a="" b="abc" if [ -z $a ] # 字符串长度为0返回true then echo "长度0" else echo "长度非0" fi if [ -n $b ] # 字符串长度不为0返回true 和-z相反 then echo "长度不为0" else echo "长度为0" fi ## if [ $a ] #字符串是否存在 # 文件测试运算符 #!/bin/bash file="/test/1.sh" if [ -r $file ] # -r 可读, -w 可写, -x 可执行, -d 是否目录 -f是否文件 -e是否存在 then echo "文件可读" else echo "文件不可读" fi ############################# 流程控制 ################################### # 单if语句可以写成一行, 用;隔开,但也必须有fi结尾 if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi # 查找当前系统中有多少个ssh进程 # 中间如果有多个判断用 elif ## read 用于从控制台读取输入. #!/bin/bash read -p "please input your name: " NAME if [ $NAME = root ] then echo "hello ${NAME}, welcome!" elif [ $NAME = itcast ] then echo "hello ${NAME}, Wlcm" else echo "SB, get out here." fi #### 注意空格不能少. ######## for循环,有几种写法 for N in 1 2 3; do echo $N; done #一句写完,循环3次 for N in {1..5}; do echo $N; done #一句写完,循环5次 for((i=0;i<=5;i++));do echo "welcome $i times"; done #和其它语言相近的写法. #或者: for((i=0;i<=5;i++)) do echo "welcome $i times" done
    # 例如 读取文件:
    for LINE in `cat /opt/dbs.txt`
    do
    /mongodb/bin/mongodump -d $LINE -o /data/backup/
    done

    #######
    while #!/bin/bash i=1 while((i<=3)) do echo $i let i++ # let是bash中用于计算的工具,变量计算中不需加$ done ####### case #!/bin/bash echo '输入1到4之间的数字:' read aNum case $aNum in 1) echo '你选择了1' ;; 2) echo '你选择了2' ;; 3) echo '你选择了3' ;; 4) echo '你选择了4' ;; *) echo '你没有输入1到4之间的数' ;; esac #注意分支的半括号和双分号. ############################# 函数 ########################################## #函数必须在使用前定义, 函数名前面可以省略function. #参数返回,可加return,如果不加,会将最后一条命令的结果作为返回值. return后跟数值(0-255) #调用时直接写函数名即可. #!/bin/bash #fun2.sh funWithReturn(){ echo "此函数会对输入的两个数进行相加运算..." echo "输入第一个数:" read aNum echo "输入第二个数:" read bNum echo "两个数分别为 $aNum 和$bNum " return $(($aNum + $bNum)) } #funWithReturn #echo "两数之和为: $?" #!/bin/bash #caller.sh . /test/fun2.sh #跨脚本调用函数 funWithReturn ####### 函数传参 #!/bin/bash funWithParam(){ echo "第一个参数为 $1 " echo "第二个参数为 $2 " a=$4 b=$9 echo $(($a + $b)) echo "第10个参数为 $10 " echo "第十个参数为 ${10} " echo "第十一个参数为 ${11} " echo "参数总共有 $# " echo "作为一个字符串输出所有参数 $* " } funWithParam 1 2 3 4 5 6 7 8 9 34 73

    模拟上传log文件到HDFS的shell示例:

    假设logs/log/ 下的access.log文件是正在采集中的日志. 而后面带有数字的 access.log.1 文件是前一天的日志文件.

    这个shell要做的是将前一天的日志都上传到hdfs上去. 如果结合crontab 就可以实现定时上传.

    upload2hdfs.sh 文件: 

    #!/bin/bash
    
    #set java env
    export JAVA_HOME=/usr/local/src/jdk1.8.0_161
    export JRE_HOME=${JAVA_HOME}/jre
    export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
    export PATH=${JAVA_HOME}/bin:$PATH
    #set hadoop env
    export HADOOP_HOME=/usr/local/src/hadoop-2.7.5
    export PATH=${HADOOP_HOME}/bin:${HADOOP_HOME}/sbin:$PATH
    
    #日志文件存放的目录
    log_src_dir=/root/logs/log/
    
    #待上传文件存放的目录
    log_toupload_dir=/root/logs/toupload/
    
    #日志文件上传到hdfs的根路径
    date1=`date -d last-day +%Y_%m_%d`
    hdfs_root_dir=/data/clickLog/$date1/
    
    #打印环境变量信息
    echo "envs: hadoop_home: $HADOOP_HOME"
    
    #读取日志文件的目录,判断是否有需要上传的文件
    echo "log_src_dir:" $log_src_dir
    ls $log_src_dir | while read fileName
    do 
        if [[ "$fileName" == access.log.* ]]; then
            date=`date +%Y_%m_%d_%H_%M_%S`
            #将文件移动到待上传目录并重命名
            #打印信息
            echo "moving $log_src_dir$fileName to $log_toupload_dir"xxxxx_click_log_$fileName"$date"
            mv $log_src_dir$fileName $log_toupload_dir"xxxxx_click_log_$fileName"$date
            #将待上传的文件path写入一个列表文件willDoing
            echo $log_toupload_dir"xxxxx_click_log_$fileName"$date >> $log_toupload_dir"willDoing."$date
        fi
    done
    #找到列表文件willDoing  ## grep -v是不包含
    ls $log_toupload_dir | grep will | grep -v "_COPY_" | grep -v "_DONE_" | while read line
    do
        #打印信息
        echo "toupload is in file:"$line
        #将待上传文件列表willDoing改名为winllDoing_COPY_
        mv $log_toupload_dir$line $log_toupload_dir$line"_COPY_"
        #读列表文件willDoing_COPY_的内容(一个一个的待上传文件名), 此处的line就是列表中的一个待上传文件的path
        cat $log_toupload_dir$line"_COPY_" | while read line
        do
            #打印信息
            echo "puting... $line to hdfs path...  $hdfs_root_dir"
            hdfs dfs -mkdir -p $hdfs_root_dir
            hdfs dfs -put $line $hdfs_root_dir
        done
        mv $log_toupload_dir$line"_COPY_" $log_toupload_dir$line"_DONE_"
    done

    假设hdfs在正常运行, 本地执行:

    cd /root
    mkdir -p logs/log
    
    vim upload2hdfs.sh
    # 将代码贴上, 检查各路径是否正确.  保存退出.
    
    chmod 755 ./upload2hdfs.sh  # 给予执行权限.
    
    ./upload2hdfs.sh 
    
    #等待成功执行完成后, 检查hdfs上是否有刚上传的文件. 

    实际案例:logstate.sh脚本 结合 crontab 定时重开日志文件:

    #!/bin/bash
    #Rotate the MongoDB logs to prevent a single logfile from consuming too much disk space.
    app=mongod
    mongodPath=/data/mongo4.2.0/bin
    pidArray=$(/usr/sbin/pidof $mongodPath/$app)
    for pid in $pidArray;do
    if [ $pid ]
    then
        kill -SIGUSR1 $pid
    fi
    done

     如果没有root权限,而crontab执行的命令中又需要sudo 则可以:

    sudo crontab -u root -e
    sudo crontab -u root -l

    注意:crond进程如果多个,会造成crontab被执行多次的情况。

    sudo 碰到重定向 > 时,权限不足。可以使用 sh -c :

    sudo sh -c "echo a > 1.txt"
  • 相关阅读:
    SpringCloud大白话之服务注册中心
    Spring事物白话文
    spring的IOC过程剖析
    2、Spring-RootApplicationContext-refresh
    1、spring与springmvc父子容器
    mysql 5.7 主从设置
    centos7下安装oracle11gR2
    lepus安装报错处理
    centos 6.9安装nginx1.4
    Linux 面试题 合集
  • 原文地址:https://www.cnblogs.com/frx9527/p/bash.html
Copyright © 2020-2023  润新知