那些年擦肩而过的 Linux 命令

如何再 AWK 中打印单引号

使用 \47,例如:

seq 0 10 | awk '{print "partition by (pfield = \47"$1"\47"}'

批量执行命令

while read line ;
do

IP=$(取到 ip)
## 简单命令直接放到这里
ssh -n ${IP} ${cmd}
## 复杂的命令放到文件中

ssh -n ${IP} < ${cmd_file}

done < $file_path

-n 的作用是 ssh 不从标准输入读数据,而是从 /dev/null 中读数据。
while do done < $file 这种方式,会将所有的内容给 while 语句,如果 ssh 不加 -n , read 只能读到第一行的内容,剩余的内容会被 shh 读到,导致只能读一行的问题。

并行执行命令

cmd_file=$(mktemp -q /path/cmd_file.XXXXX)
if [ $? -ne 0 ]; then 

 echo "$0: Can not create"
 exit 1 
fi

while .. 
do

echo "cmd string" >> ${cmd_file}

done 

eval $(cat ${cmd_file})

1和2 append 到文件中

commad >> log.file 2>$1

单行处理管道中的数据


conmmad | \
while read line; 
do
  echo $line
done

read args1 args2 args3 ;

echo $args1

编辑文末 n 行

sed -e ":a " -e "$action ; N ; 2,n行数字ba" -e "P;D" file_path

找出不包含某个字符的文件

grep -L '字符串' ./文件名字

分割文件

# 每 1G 就分割一个文件 
split -c 1G file pre_fix 

cp 的升级版


rsync -av --exclude 排除某些文件

命令超时

		timeout -- run a command with a time limit
SYNOPSIS
		timeout [OPTION] DURATION COMMAND [ARG]..

DESCRIPTION

       Start COMMAND, and kill it if still running after DURATION.

       Mandatory arguments to long options are mandatory for short options too.
       -k, --kill-after=DURATION

              also send a KILL signal if COMMAND is still running

              this long after the initial signal was sent

       -s, --signal=SIGNAL

              specify the signal to be sent on timeout;

              SIGNAL may be a name like 'HUP' or a number; see 'kill -l' for a list of signals

拦截 hive 命令每次执行的命令

ps -ef | grep 'hive.beeline' | grep '\-f' | awk '{print $2}'

export data dictionary from hive

#!/bin/bash -x
function desc_dict(){
        db=$1
        tables=$(hive -e --showHeader=true " use $db ; show tables; " | sed "s/|//g ; s/[-+]//g ; s/tab_name//g" | xargs )

        for table in $tables
        do

          echo "$db.${table//|/}" >> out.dict
          hive -e --showHeader=true -e " use  $db ;  DESCRIBE ${table//|/} " >> out.dict
        done

}

结合 python 在把 txt 文档转为 insert 语句或者其他的格式。https://gitee.com/bluedream_pp/pythonFirstInHead/blob/master/gen_data_dictionary_insert_sql.py

计算任务耗时

grep 'duration' ${filepath} | grep -v 'echo' | sed 's/-//g' | \
awk '{ {print $1 , $7}}' | sort -k2 -r -n | \
awk 'BEGIN{printf "%-28s,%5s\n","任务","耗时" } { printf "%-30s,%5s 秒\n",$1,$2}' >> ${filepath}

sed 批量执行命令

sed "s/\(.*\)/grep -o '\1' log.log /e" k.txt

文件路径

$> cat s.sh
#!/bin/bash -x
declare -r curr_dir=$(cd `dirname $0` ; pwd)
$> sh s.sh # 1 
$> cd ..
$>sh folder/s.sh # 2

三个知识点:

  1. basename 路径或者文件路径:取出路径或者文件路径中除最后一个路径之前的相对路径。
  2. dirname 路径或者文件目录:取出路径或者文件路径中最后一个路径。
  3. $0 是 shell 中的预定义的变量,意思是文件的相对路径。

例如,#1 中式当前目录是 .,所以 basename $0 结果是s.shdirname $0的结果是 .
#2 中的往前推了一级目录,所以 basename $0结果是s.sh

取 k-v 值

$>cat k-v.txt
1=tom
2=java
3=python
$> cat k-v.txt | sed -n '/[0-9]=tom/ s/[0-9]=\(.*\)/\1/p '

在命令行中添加代码块

sed -i -e '/^[sed|grep|cat|awk|ss|ifcofig|echo]/ i ```bash' -e '/^[sed|grep|cat|awk|ss|ifcofig|echo]/ a ```' linux_sed_awk_grep.md

正则查找分组内容

grep 'aaa:\(.*\)' t.txt | sed -n ' s/aaa:\(.*\)/\1/ ; p'

查看有哪些 sql 脚本在跑

ps -aux | grep org.apache.hive.beeline.BeeLine  | awk '  $1="user_name" {print $0}' | grep .sql

awk 格式化输出

引用文章
当然也可以ask man, 这里主要讲 awk 的内置函数 printf 的用法。

awk '{printf "%-11s,%12s",$1,$2}'

format

跑批工具函数


#功能描述:
# 1. 根据 shell 路径和参数执行任务
# 2. 如果遇到 exception 之类的问题,首先是重跑任务,然后是将错误(todo)信息到企业微信
# 3. 另外,todo: 增加捕捉异常的逻辑,思路是将根据当前的进程号找到该进程占用的日志文件,然后从日志文件中找出报错信息。
function run_hive(){
  arguments=$*
  echo $arguments
  job_name=`echo $arguments | sed 's/.*-f\(.*\)\.sql.*/\1/g'`
  count=0
  # JOB执行失败重试过程,失败一分钟后重试
  while [ 0 -eq 0 ]
  do
    echo ".................. ${job_name##*/} start at `date "+%Y-%m-%d %H:%M:%S" `  ..................."
    hive ${arguments}
    if [ $? -eq 0 ]; then
          echo "--------------- ${job_name##*/} done at `date "+%Y-%m-%d %H:%M:%S" `  ---------------"
          break;
      else
          # 执行失败,重试
          count=$[${count}+1]
          # 指定重试次数,重试超过3次即失败
          if [ ${count} -eq 4 ]; then
              alert_dw -t wework -g 预警消息群 -j ${job_name##*/} -m "${job_name##*/} retry 3 times , and failed" -o 3
              exit 10
              break
          fi
          echo "................${job_name##*/} after 60s retry .............."
          sleep 60
      fi
  done
}

通过端口查看 hive 任务

ss -pnt src *:10000 | awk 'NR>1 {print $5}' | cut -d ":" -f2 | xargs -I{} lsof -i:{}

sed 替换

sed 的精确匹配:  's/\<store_cn\>/store_nm_cn/g'
sed 正在匹配后,单词大小转换:'s/正则表达式/\U&/g'(大写),'s/正则表达式/\L&/g'(小写)
sed 组匹配: 's/is_\(.*\)/\1_ind/g' 正则查找后,使用括号里面的内容替换,这个例子就是匹配以`is_`开头的单词,然后替换成使用括号里面的内容
+ `_ind` 替换。完成的功能就是将标识字段(is_xxx)转成 使用 _ind 结尾

查看批量任务执行状态

find ./recap_dm* -name 'log.log' | xargs lsof | awk '{if(NR>1){print $9}}' | uniq -c

执行最多的命令

history | grep 'git' | grep 'history' -v | awk '{$1="";print $0}' | sort | uniq -c | sort -r -k1 | head -10

截取日期

#!/bin/bash -x


index=$1
start_date=$2
#
rs=`hive --showHeader=false -e "
select
     date_id_lyw_fd_wm  
    ,date_id_lyw_ld_wm  
    ,date_id_w_fd_wm    
    ,date_id_w_ld_wm    
 from db.dim_date_d
where date_id = '${start_date}' "`

echo ${rs//[ +-]/}

echo ${rs//[ +-]/} | tr '|' ','  | awk -F','  'BEGIN{} \
                    {for(i=1;i<=NF;i++){if((i-1)=="'$index'"){rs[i]=$i}}}\
                    END{for(ii in rs ) {print rs[ii]}}'

# 函数的形式

function get_date(){
        index=$1
        start_date=$2
        rs=`hive --showHeader=false -e "
        select
             date_id_lyw_fd_wm
            ,date_id_lyw_ld_wm
            ,date_id_w_fd_wm
            ,date_id_w_ld_wm
         from DB.dim_date
        where date_id = '${start_date}' "`

        ss=$(echo ${rs//[ +-]/} | tr '|' ','  | awk -F','  '{for(i=1;i<=NF;i++){if((i-1)=="'$index'"){rs[i]=$i}}} END{for(ii in rs ) {print rs[ii]}}')
       echo $ss
       return 0
}



v1=$(get_date 1 20200101)
echo $v1


这里需要注意的是 return 和 Java 中的 return 并不一样的,在 bash 中 return 返回的是函数退出时候的返回码,要想返回计算结果,需要使用 echo 命令。

去掉文本中的 BOM

utf-8 还有 utf-8 with bom 的格式,如果是这种格式的话,
在执行
hive -f file.sql 的时候,会报错。
单个文本的情况下,可以使用下面的方法:

使用 set nobomb 命令
:set nobomb 
:x

批量更改的命令:

ls *.sql | xargs sed -i 's/\xef\xbb\xbf//g'

使用 presto 命令文件


grep -R 'presto-client' ./* | awk -F: -v OFS="---" '{print $1,$2}' | sed 's/--catalog.*//g; s/num=`//g' > ~/presto.txt

批量 explain


#!/bin/bash -x


sql_file_path=$1
out_file=$2

temp_path=$(mktemp -t -d explain_XXXXX)

cp -r $sql_file_path $temp_path/

cd $temp_path
find $temp_path -name '*.sql'
for file in `find $temp_path -name '*.sql'`
do

  sed -i 's/\;/\n\;/g' $file
  file_path=${file%/*}
  cd ${file%/*}
  csplit $file  /\;/ -s  {*} -n2 -f 'split' -b "%02d.sql"

  for f in `ls $file_path/split*.sql`
  do

     sed -i "1i explain " $f
     sed -i " s/\;//g" $f
     if [ `grep "select" $f | wc -l` -gt 0 ]; then
       if [  `grep "insert" $f | wc -l` -gt 0 ]; then

         sed -i "1i set hive.exec.dynamic.partition.mode=nonstrict; " $f

       fi

       hive -f $f


     fi


  if [ "$?" -gt 0  ]; then
    echo 'error $file' >> $out_file

  fi

  done


#exit 0

done

去除可见字符

sed -i " /^$/d ; s/[[:space:]]//g" split02.sql
--删除行首空格
sed 's/^[ \t]*//g'

删除历史的数据

find $curr_dir/  -name '*.txt' -ctime +7  -exec rm -f {} \;

UUID

cat /proc/sys/kernel/random/uuid

进程的管理

//https://www.cnblogs.com/itech/archive/2012/09/16/2687404.html
nohup command args // 忽略所有的hangup信号 ,ssh 后的 exit logout 断网都属于 hangup

setsid 

jobs -l 查看后台进程

通过以下命令,我们可以对放入到后台的命令进行控制

查看当前终端下的后台进程:
直接执行:jobs

将查看到的某个后台进程放回到前台:
直接输入:fg {jobid} //这里的{jobid}是通过jobs命令中看到的进程前[]中的数字。

将当前正在前台运行的进程放到后台运行:
先敲下快捷键:ctrl +z //暂停当前正在运行的进程。
再执行:bg

终止当前正在前台运行的进程:
直接敲下快捷键:ctrl +c


disown亡羊补牢,为没有使用nohup与setsid的进程加上忽略HUP信号的功能。

使用方法:
将当前正在前台运行的进程放到后台运行(ctrl+z和bg);
然后执行disown -h %{jobid} //这里的{jobid}是通过jobs命令中看到的    进程前[]中的数字。

执行历史命令

!-{prefix-word}

例如:

!-his : 执行匹配的以 his 开头命令

sort 命令的应用

cat /etc/passwd | sort -k3 -t : | head -2

-k 是关键词,类比, -k1 --> order by 1 
-t seperate , 例如 , -t :  --> 使用 : 分割符号

不退出 .sh 文件,执行 .sh


1. shift + ;
2. :!bash -x % 
3. :r !ls *.sql -- 取出当前目录下 sql 文件的名字放到当前行
其中 % 就是代表了当前的 shell 文件



如何生成临时文件

生成独一无二的文件名称的场景下,我们可以是使用 $$ 就可以了,例如 sed expression file > file$$

正如 shell 中,只要你想不到,没有做不到。 shell 有一个的维护临时文件的命令:

mktemp -[ d | t] sql_XXXXXX.sql

d:是临时目录
t:在系统默认的临时文件的路径写新建文件,一般是 /tmp/

XXXXX 是站位符,mktemp 会给我们自动生成几个符号

egrep 的应用

cat log.log | egrep  '任务启动时刻|任务结束时刻|任务总计耗时|任务平均流量|记录写入速度|读出记录总数|读写失败总数' | xargs echo | awk '{print "\""$20"\",\""$23"\""}' |  sed 's/"//g' | cut -d ',' -f 1

wordCount

[root@s4 ~]# cat d.txt
db.t1
db2.t2
aaa aaa
aaa
aaa
aaa
aaa
aaa


[root@s4 ~]# cat d.txt | tr ' ' '\n' | uniq -c
      1 db.t1
      1 db2.t2
      7 aaa

cat work.txt

cat work.txt | tr ' ' '\n' | awk 'BEGIN{print "word","count"} \
                   {rs[$1]++} \
                    END{for(i in rs ){print i,rs[i]}}\
'


cat work.txt | awk 'BEGIN{print "word","count"} \
                    {for(i=0;i<=NF;i++){rs[$i]++}}
                    END{for(i in rs ){print i,rs[i]}}\
'

先整理一下 awk 的通用格式

awk [-f] [-F] [-v] [-FS] [-OFS] 'BEGIN{expresion} row_filter_regexp_expression {action} END{expression}'

BEGIN:在遍历每一行之前做的操作
END:遍历完每一行之后做的操作
row_filter_regexp_expression:使用正则表达式,或者逻辑表达式来过过滤行,相当于 where
{action} 处理里面的每一行,就会 select 一样

多行合并

sed ':a ; N;s/\n/ / ; t a ; ' file

通常的认为下面会 sed 会替换没一行上的回车,但是不会,如果要想替换回车,需要 tr '\n' ''
tr --> translate

[root@s4 ~]# cat d.txt | sed 's/\n//g '
db.t1
db2.t2
aaa
aaa
aaa
aaa
aaa
aaa

[root@s4 ~]# cat d.txt | sed ' N ;s/\n/,/g '
db.t1,db2.t2
aaa,aaa
aaa,aaa
aaa,aaa

[root@s4 ~]# cat d.txt | sed ':a ; N ;s/\n/,/g ; t a '
db.t1,db2.t2,aaa,aaa,aaa,aaa,aaa,aaa

最简单的:

cat d.txt | xargs

拼接 sql 语句中的 in ('A' ,'b')
>cat t.txt 
A
b

>cat t.txt | awk '{print "'\''"$1"'\''"}' | sed ':a ; N ;s/\n/,/g ; t a '
'A','b'

使用 sed 替换,\t

cat file | sed "s#,#\t#g"

查看主机上所有的 git repository 已经状态

find ~ -name ".git" 2> /dev/null | sed 's/\/.git/\//g' | awk '{print "-------------------------\n\033[1;32mGit Repo:\033[0m " $1; system("git --git-dir="$1".git --work-tree="$1" status")}'

刷新历史数据的例子

// example.sh 20190501 20190531
// 数据从 20190501 刷新到 20190531

#!/bin/bash -x

start=${1:?please input start_date}
end=${2:?please input end_date}

i=0

while [ ${start} -le $end ] 
do

  bash -x wyf.sh $start
  start=$(date -d " $start 1  day " +%Y-%m-%d)
  i=$(($i+1))

done

// 传入的参数是 example.sh 1
// 这个意思是从从昨天,往前刷新 1 天的数据

#/bin/bash -x

for (( i = 1; i <= $1; i++ )); do

  date=$(date -d"-$i day" +%Y-%m-%d)
  echo $date
  bash -x run_all.sh $date $date

done


#!/bin/bash -x

start=${1:?please input start_date}
end=${2:?please input end_date}


while [ `date -d ${start} +%s` -le `date -d "$end" +%s` ] 
do

  bash -x $3 $start 
  start=$(date -d"${start} 1 day" +%Y-%m-%d)

done

#!/bin/bash -x



start=${1:?please input start_date}
end=${2:?please input end_date}
order=$4

if [ $order = 'desc' ]; then

while [ `date -d ${start} +%s` -le `date -d "$end" +%s` ]
do

  bash -x $3 $end
  end=$(date -d"${end} -1 day" +%Y-%m-%d)
done

exit 0 ;

fi

while [ `date -d ${start} +%s` -le `date -d "$end" +%s` ]
do

  bash -x $3 $start
  start=$(date -d"${start} 1 day" +%Y-%m-%d)
done



show ip

ifconfig | awk '$1="inet" && $2 ~ /addr:[0-9]+/ {print $2}' | awk -F ':' ' $2 != "127.0.0.1" {print $2}'

ifconfig | awk '$1="inet" && $2 ~ /[0-9]{2,3}\.[0-9]{2,3}\.[0-9]{2,3}\.[0-9]{2,3}/ {print $2}'

show diretory like tree

ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/   /' -e 's/-/|/'

查看连接你服务器 top10 用户端的 IP 地址

netstat -nat | awk '{print $5}' | awk -F ':' '{print $1}' | sort | uniq -c | sort -rn | head -n 10

随机产生 32 的密码

tr -dc 'a-zA-Z0-9~!@#$%^&*_()+}{?></";.,[]=-' < /dev/urandom | fold -w 32 | head -n 1

多行数据合成一行

ls *.sh | awk '{print NR":/data/app/product/yc_data/workflow/biz/dm/deliver/dm_deliver/"$1}' | sed  ':a;N;$!ba;s/\n/;/g'

取文本中的某个值

tail -100 his_out.log | grep '读出记录总数' | cut -d ':' -f 2 | sed s/' '//g

日期

#!/bin/bash -x 


today=${1:-`date -d " -1 day " +%Y%m%d `}
## the first day of last month
first_day=$(date +%Y%m )01
## the first day of this month
last_month_first_day=$(date -d " -1 month" +%Y%m )01
## the fist day of the month` the first day 

week=`date -d "$first_day" +%w`
if [ $week -eq 0 ] ; then
  week=7
fi
((week--))
monday=`date -d  " ${first_day} -${week} days" +%Y%m%d`


week=`date -d "$last_month_first_day " +%w`
if [ $week -eq 0 ] ; then
  week=7
fi
((week--))
last_month_monday=`date -d  " ${last_month_first_day} -${week} days" +%Y%m%d`

week=`date -d "$today" +%w`
if [ $week -eq 0 ] ; then
  week=7
fi
((week--))
## 本周星期一的日期
monday=`date -d  " ${today} -${week} days" +%Y%m%d`
## 本周星期日的日期
sunday=`date -d  " ${monday} +6 days" +%Y%m%d`
## 上周星期一的日期
last_week_monday=`date -d  " ${monday} -7 days" +%Y%m%d`
## 上周星期天的日期
last_week_sunday=`date -d  " ${sunday} -7 days" +%Y%m%d`
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值