常用 Bash Shell 整理

常用 Bash Shell 整理

2014 年 1 月 26 日

bash脚本的参数

手工的处理方式:

  • $0: 指脚本自己, 例如 test.sh.
  • $1: 第一个参数, 依次类推 $2, $3 ...
  • $#: 参数的个数.
  • $@: 所有的参数, 是一个数组.
  • $*: 所有的参数, 与$@不一样的是它是一个字符串.

一个简单的使用sample:

for arg in "$@"
do
    echo $arg
done

getopts的处理方式:

(这里只讨论短选项, 长选项需要getopt, 会复杂一些).

while getopts "a:bc" arg
do
    case $arg in
        a) echo -e "argument a: $OPTARG\n" ;;
        b) echo -e "argument b\n" ;;
        c) echo -e "argument c\n" ;;
        ?) echo -e "usage: ./test <-a **> <-b> <-c>" ;;
    esac
done

上面这个sample中:

  • "a:bc"代表了-a需要参数, b和c是无参数的选项.
  • case ? 代表了任何不识别的选项.

获取当前脚本目录

function get_pwd()
{
    echo "$( cd "$( dirname "$0" )" && pwd )";
}

遍历嵌套文件夹

function loop_dir()
{
    dir="$1";
    for sub in $dir
    do
        if [ -d "$sub" ]; then
            loop_dir $sub;
        else
            # do something
        fi
    done
}

expect的典型用法

只有 spawn 的内容才能 expect 捕获到, expect 的内容包括了: 终端的输出, EOF 和超时.

一个自动登陆的 sample:

#!/usr/bin/expect

set timeout 30
spawn ssh root@192.168.1.199 -p 22

expect {
    "(yes/no)?" {send "yes\r"}
}
expect {
    "Password:" {send "****\r"}
}
expect {
    "#" {send "cd /home/software\r"}
}

# 等待交互,如果此处不用interact,就会自动退出了
interact

再看一个 bash 中的 sample:

function scp_target()
{
    scp_src="$1";
    scp_dst="$2";
    scp_dst_passwd="$3";
    expect -c "set timeout -1;
        spawn scp -p -o StrictHostKeyChecking=no -r $scp_src $scp_dst;
        expect "*assword:*" { send $scp_dst_passwd\r\n; };
        expect eof {exit;}; "
}

进程锁

通过flock实现进程锁, 尤其在执行shell脚本时比较实用, 具体可以参考man page.

一个典型用法如下:

# non-block (fail exit with code 1), exclusive lock
flock -xn /tmp/test.lock -c test.sh

# non-block, wait 5 seconds
flock -n -w 5 /tmp/test.lock -c test.sh

绑定cpu

在某些情况下, 可以通过绑定server进程到固定的cpu, 减少context切换, 一定程度上提高性能. 这个时候需要用到taskset.

taskset的具体用法可以参照man page, 一个常见的sample如下:

taskset -c 0,2,4-6 -p 14285

定时任务

如果没有root权限, 除了crontab之外, 还可以手夯脚本来实现定时任务, 如下面的例子:

#/bin/sh
while [ 1 -eq 1 ]; do
    date >> /tmp/date.tmp
    # sleep 的单位是秒
    sleep 300
done;

数学计算

shell的数学计算, 个人最常用的有三种:

  • (())方式, 支持简单运算;
  • expr方式, 支持简单运算, 需要注意的是: expr的"|", "&", "<", "<=", ">=", ">", "*" 运算符需要做转义;
  • awk方式, 可以进行浮点运算;
#/bin/sh

var=1;

#  (())方式
echo $((var + 1));

#  expr方式, 因为转义符就是间隔号, 间隔号转义自己打印不出来, 蛋疼……
echo ``expr $var + 1``;

#  awk方式
echo "$var 1" | awk '{print($1 + $2)}';

批量修改文件名

其实是正则+sed 的应用, sample 如下:

#/bin/sh
find . -name "*target_from*" | sed 's/\(.*\)\(target_from\)\(.*\)/mv \1\2\3 \1target_to\3/' | sh

合并文件中的多行

有个 Win 风格的文本文件(\r\n换行), 想合并其中 i, i+1, i+2 行, 可以这么操作:

sed 'N;N;s/\r\n/ /g' source

统计网络连接来源

其实是 awk + sort + uniq 的应用:

#/bin/sh
netstat -anp | grep ESTABLISHED | awk '{print $5}' | awk -F ':' '{print $1}' | sort | uniq -c | sort -r

AWK

awk是一个很强大的工具, 具体的细节就不多说了, 直接贴一段代码.

#!/bin/sh

# 从日志文件中获取最后n次记录
function get_last_n()
{
    input=$1
    lastn=$2
    output=$3

    # do reverse
    awk '
        BEGIN {
            FS = "|"
            sum = 0
        }
        {
            if (NR != 1 && NR != 2)
            {
                data[sum] = $0
                sum ++
            }
        }
        END {
            for (i=sum-1; i>=0; i--)
            {
                print data[i]
            }
        }
    ' $input > $input.reverse

    # sort first n
    awk -v lastn="$lastn" '
        BEGIN {
            FS = "|"
            num = 0
        }
        {
            if (record[$2] < lastn)
            {
                result[num] = $0
                num ++
                record[$2] ++
            }
        }
        END {
            for (i=num-1; i>=0; i--)
            {
                print result[i]
            }
        }
    ' $input.reverse | sort  > $output

    rm $input.reverse
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏用户2442861的专栏

JavaWeb工程中web.xml基本配置

        先说下我记得xml规则,必须有且只有一个根节点,大小写敏感,标签不嵌套,必须配对。

1741
来自专栏FreeBuf

Node.js中的内存泄漏分析

内存泄漏(Memory Leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。如果内存泄漏的位置比较关键,那么随着处理的进行可能持有越来越多的无用...

4715
来自专栏北京马哥教育

3000 字 Flask 快速学习指南:从入门到开发

作者:过了即是客 Flask是一个Python编写的Web 微框架,让我们可以使用Python语言快速实现一个网站或Web服务。本文参考自Flask官方文档,...

6569
来自专栏Python绿色通道

使用Python开发你的第一个服务器程序

声明:本文是用Py3.6版本,而且从此以后我的系列文章优先使用Py3.6版本,为什么说优先使用Py3.6版本呢?因为有的时候Py3.6版本确实有些问题,那我只能...

1.8K2
来自专栏用户2442861的专栏

Linux下动态库(.so)和静态库(.a) 的区别

动态库(共享库)的代码在可执行程序运行时才载入内存,在编译过程中仅简单的引用,因此代码体积比较小。

1.9K1
来自专栏决胜机器学习

《Redis设计与实现》读书笔记(二十八) ——Redis集群节点结构与槽分配

《Redis设计与实现》读书笔记(二十八) ——Redis集群节点结构与槽分配 (原创内容,转载请注明来源,谢谢) 一、概述 redis集群是...

4456
来自专栏程序员同行者

django基础之二

1344
来自专栏信安之路

看我如何收集全网IP的whois信息

今天给大家分享几个脚本,看看如何收集全网whois信息。首先了解一下whois.py这个基本程序。

1520
来自专栏前端萌媛的成长之路

JavaScript模块化发展

3283
来自专栏技巅

Glusterfs之rpc模块源码分析(中)之Glusterfs的rpc模块实现(1)

1793

扫码关注云+社区

领取腾讯云代金券