您的位置:首页 > 运维架构 > Shell

一些 Shell 脚本(持续更新)

2015-05-24 13:39 323 查看

1. 启动日志分析

启动日志格式如下:

开机时间:2015/05/13 周三 16:45:17.79

关机时间:2015/05/13 周三 18:46:03.91

开机时间:2015/05/14 周四 17:07:11.80

开机时间:2015/05/14 周四 17:09:34.68

关机时间:2015/05/14 周四 18:42:35.40

转换为导入 excel 的格式:

2015/05/13 16:45:17.79 18:46:03.91

2015/05/14 17:07:11.80

2015/05/14 17:09:34.68 18:42:35.40

显然有些项缺失,可能导致错误配对,但假定只有关机项会缺失吧

代码

预处理文本

先把“时间:”替换为空格

补充:若能进一步把 \n关机时间: 替换为空,则下一步处理会更简单!

awk 处理

Markdown 中可以用全角空格或html转义符来保持代码缩进

半方大的空白 或 

全方大的空白 或 

不断行的空白格 或 

{

   if ($1 == "开机") {

     if (ss == 1) {

      print ""

     }

      printf $2" "$4

      ss = 1 # 标识上次是否是开机

   } else {

       if (ss == 1) {

        print " "$4

        ss = 0

       } else {

        print $2" "$4

       }

   }

}


运行

Windows 下可以使用 gawk_win32 来处理

gawk 4.1.0

http://pan.baidu.com/s/1mguTqRI

http://code.google.com/p/gnu-on-windows/downloads/list

2. 远程通知

项目在服务器上需要长时间编译,如何在编译完成后提醒自己?

环境:一台自己用的机器,一台服务器。

代码

服务器: echo 'Done!' | nc 127.0.0.1 9000

机器:notify-send $(nc -l 9000)

3. 并行处理文件

有N个1-2 G大的文件,其中第六列是点分表示的IPV4地址,需要把它转为整数表示。

#!/bin/awk -f

{

  len = split($6, a, ".")

  ip = 0

  if (len == 4) {

    ip = lshift(a[1], 24) + lshift(a[2], 16) + lshift(a[3], 8) + a[4]

    printf $1"\t"$2"\t"$3"\t"$4"\t"$5"\t"ip"\n" > o

  }

}


CPU是6核的,就起了6个进程去转,每个awk进程基本都是CPU 100了

但转换一个文件还是需要15分钟左右,还是太慢

求教有什么方法可以让AWK跑的更快些吗?

4. 移除文件名里的特殊字符

中了病毒,所有xls文档后缀被改为scr,且有个不知道什么符号把字符串左右反转了

分析

我用的 zsh,补全文件名时可以看见其中有个特殊字符,显示为:6-7生產產值(2)<202e>slx.scr。

查了下 202e,发现是个特殊的 unicode 字符,用来左右反向文字。

这样病毒的伎俩也很清楚了,文件实际后缀是 slx.scr(可执行),但显示出来是 rcs.xls!不过狐狸尾巴没完全藏住。

如何移除这个特殊字符?确实费劲,毕竟 shell 处理这种不可见特殊字符很不给力

首先想到 rename,支持 perl 正则,还挺强大的。那么删掉这个 unicode 字符就行了

rename "s/\u202e//g" —— 移除失败

detox -s utf_8 -v -n —— 失败,中文也被移除

rename "s/[\x2e\x20]//g"

rename "s/[\x20][\x2e]//g"

rename -e "s/[^[:print:]]//g" —— 中文被移除

rename "s/[\e2\x80\xae]//g" —— 乱码了!

好了,放弃精确匹配,改用模糊匹配

rename "s/.{3}slx.scr/.xls/g" *.scr —— 成功!

试了下 bash,直接跪了,看不见,但直接 mv 是有效的:mv 6-7生產產值(2)slx.scr 6-7生產產值(2).xls

不知道有什么小工具能直接查看(hex)并处理文件名特殊字符的?不过可以用 vim 打开文件夹,看到文件名的特殊字符

5. 临时文件夹清理脚本

每一小时检查一次,如果文件夹大于3G,则开始清理文件夹里的文件,无子文件夹

清理的时候,按时间顺序清理文件。

如果文件有人使用,则不能使用rm暴力删除,使用cat /dev/null>文件名

文件夹小于500M时停止清理。

想法

文件夹大小查看可用 du 命令;按时间顺序,可以用 ls 的 sort 选项;定时,cron

不过要检测文件是否有人使用,用 lsof 或 fuser 好像不太灵光,要 root?

而且使用检测导致批量删除文件不太方便,还是一个个来吧。

DIR="/tmp/"

dir_size=$(du -ms "$DIR" | cut -f1)

max_size=3000 #MB

min_size=500

[ "$dir_size" -lt "$max_size" ] && exit 0

del_size=$(((dir_size - min_size)*1024)) #KB,将清理的文件大小

pushd "$DIR" || exit 1

ls -tl | awk -v ds="$del_size" '{

 if (NF > 8) {

  sz += $5; nm = $9; # 获得文件大小(B)和文件名

  system("lsof "nm" && cat /dev/null>"nm" || rm -f "nm);

  #~ "lsof "nm" 2>/dev/null" | getline used; print "used:"used

  if (rshift(sz,10) >= ds) exit; # 策略有些激进,先删除再判断

 };

}'


6. 文件夹监控压缩脚本

环境:win10

要求:一个文件夹里不定时的会放入不少word、PPT文档。

怎样实现即时放入一个文档后,自动使用Winrar生成一个单独的压缩包?手动实在麻烦

想法

用 IFTTT 之类的软件就可以,比如 https://www.nodesoft.com/foldermonitor

如果想要轻量级的方案,自然脚本是首选,但批处理循环检测的做法还是太 low

下面请出 powershell,从 win7 就开始内置,win10 更不用说。基于 .net framewrok,功能强大的系统管理工具。

$folder = 'C:\Users\Administrator\Documents' #监控文件夹

$zipPath = $env:ProgramFiles + '\7-Zip' #压缩程序路径

$env:Path = $env:Path + ';' + $zipPath

Set-Location -Path "$folder"

$watcher = New-Object System.IO.FileSystemWatcher

$watcher.Path = $folder

$watcher.IncludeSubdirectories = $false

$watcher.EnableRaisingEvents = $true

$created = Register-ObjectEvent $watcher "Created" -SourceIdentifier "FileWatcher" -Action {

 $name = $Event.SourceEventArgs.Name

 $type = $Event.SourceEventArgs.ChangeType

 if ($name -notmatch ".*`.(rar|zip|7z)$") {

  Write-Host "$name"

  7z.exe a "$name.7z" "$name"

 }

}

# 停止监控可手动运行如下命令:

# Unregister-Event FileWatcher


脚本使用了 .net 对象及其事件机制,不愧是面向对象的 shell

运行的话有点麻烦,ms 为了安全,默认不允许双击运行。可参考“快速运行 .ps1 脚本的 N 种方法”。

我采用第一种,配一个同名的 .cmd 批处理文件来启动,内容如下:

@set Path=%Path%;%SystemRoot%\system32\WindowsPowerShell\v1.0 & powershell -ExecutionPolicy RemoteSigned -NoExit -NoProfile %~dpn0.ps1

7. 批量替换词典数据

共两个文件:词典和替换表

替换表包含多行,每行内容为:查找内容 替换成的内容。要求全字匹配把词典替换完

代码

while read s ts; do sed -i "s/${s}/${ts}/g" "$1"done < list

8. Win 注销后自动休眠

问题:

当前用户注销后,用户进程会全部退出,后继无法再操作。这里使用 system 用户执行计划来达到注销后的操作,所以必须用管理员权限执行脚本

计划延时 2 分钟后执行,给注销留点时间。这里直接加了分钟,有 bug

正确做法应先把总时间转换成秒,再累加较好

批处理代码

@echo off & setlocal enabledelayedexpansionset /a mt=(%time:~3,2% + 2) %% 60if %mt% lss 10 (set mt = 0!mt!)set st=%time:~,2%:!mt!SCHTASKS /Create /F /SC ONCE /RU SYSTEM /TN "HibernateHelper" /TR "shutdown /h" /ST %st%

9. 文件名处理

有多个文件如:[牛人]Dear Annie_高清_纯音频文件_纯音频输出.mp3

       [牛人]My Friend_高清_纯音频文件_纯音频输出.mp3

怎么写bat,能把有重复部分的文件批量改为:

        [牛人]Dear Friend.mp3

       [牛人]My Destiny.mp3

想法

经确认,需删除的相同字段只会在首部、中部或尾部

本质上是求字符串的重复部分(2 个字符以上);但会有明显特征,不算随机字符串

有用部分也可能重复,故有误杀可能

这里只处理了尾部重复,这种情况应该比其它情况多

#Requires -Version 2.0

 

$chars = @{} # 特征字符串

$append = @{} # 待定文件名

 

$ext = "mp3"

$files = dir *.$ext | % { $_.basename }

 

:DONE for ($i = 0; $i -lt $files.Count; $i++) {

  $a = $files[$i]

foreach($str in $chars.Keys) {

  if ($chars[$str] -lt $a.Length) {

  $idx = $a.IndexOf($str)

  if ($idx -gt 0) {

   $new = $a.Substring(0, $idx)

   rename-item "$a.$ext" "$new.$ext"

   continue DONE

  }

  }

}

$s = $a

foreach($b in $append.Keys) {

  if ($s.Length > $b.Length) {

    $s, $b = $b, $s

  }

  for ($j = 0; $j -lt ($s.Length - 1); $j++) {

   $subStr = $s.Substring($j)

    $idx = $b.IndexOf($subStr)

    if ($idx -gt 0) {

    $newA = $s.Substring(0, $j)

    $newB = $b.Substring(0, $idx)

   echo "2.1: mv $s.$ext $newA.$ext"

   echo "2.2: mv $b.$ext $newB.$ext"

   $chars["$subStr"] = $subStr.Length

    $append.Remove($b)

    continue DONE

    }

   }

  }

 $append[$a] = 1

}


10. Execute remote script with passing to it some arguments

curl -s http://server/path/script.sh | bash /dev/stdin arg1 arg2

11. 递归批量修改任意文件后缀

find "$path" -type f -execdir rename 's/.[\w]+$/.htm/' '{}' +

12. 文件按序命名

有文件:2334.jpg ds23l.jpg 壁纸01.jpg 乱七八糟文件名.jpg

请问怎么把这些jpg文件批量重命名成如下:

1.jpg 2.jpg ... 100.jpg

或是:

001.jpg 002.jpg ... 100.jpg

ls -A1 | nl -w3 -n rz | while read num name; do mv $name $num.jpg; done


13. 词典文件按行去重

有英文词库文件,内容类似:

zymotic zymotic

zymotic zymotic 17700

zz zz

Zz Zz

zz zz 3780000

怎么把前两列相同的去重:

zymotic zymotic 17700

zz zz

Zz Zz

awk '!array[$1]++'
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: