进程

linux 多用户多任务 进程/线程
ps     显示系统中所有进程
ps -ef
ps -aux
ps -auxfww
ps -u postfix -aflww   #查看指定用户的详细进程
pstree  #树形方式显示
pgrep   #从运行进程队列中查找进程
linux命令可以从两个地方读取要处理的内容,一个是通过命令行参数,一个是标准输入。
通过xargs命令,可以在管道后面使用那些不接收标准输入的命令了
例如:
find /etc -name *.conf | ls -l
find /etc -name *.conf | xargs ls -l

pgrep -u postfix -l    #查看特定用户的所有进程
pgrep -u apache -l | xargs kill -9   #杀死apache用户的所有进程

pidof cp  #查看pid号
3504
sleep 10; kill -s 18 3504 ; sleep 10 ; kill -s 19 3504 ; sleep 10 ; kill -s 9 3504

tty 物理终端  7个 ctrl+alt+f1~7
pts 虚拟终端

企业shell面试题

1.mysql分数据库备份脚本
#/bin/sh
MYUSER=root
MYPWD=123456
SOCKET=/tmp/mysql.sock
MYCMD=”mysql -u$MYUSER -p$MYPWD -S $SOCKET”
MYDUMP=”mysqldump -u$MYUSER -pMYPWD -S $SOCKET”
for database in `$MYCMD -e “show databases;|sed ‘1,2d’|egrep -v “mysql|schema”`
do
$MYDUMP $database|gizp >/server/dackup/${datebase}_$(date +%F).sql.gz
done
mysql分表备份
#/bin/sh
MYUSER=root
MYPWD=123456
SOCKET=/tmp/mysql.sock
MYCMD=”mysql -u$MYUSER -p$MYPWD -S $SOCKET”
MYDUMP=”mysqldump -u$MYUSER -pMYPWD -S $SOCKET”
for database in `$MYCMD -e “show databases;|sed ‘1,2d’|egrep -v “mysql|schema”`
do
mkdir /server/backup/${datebase} -p
for table in `$MYCMD -e “show tables from $database;”|sed ‘1d’`
do
$MYDUMP $datebase $table|gzip >/server/backup/${database}/${database}_${table}_$(date +%F).sql.gz
done
done

2.bash for循环打印下面这句话中字母数不大于6的单词
I am oldboy teacher welcome to oldboy training class
a.for循环
b.对字符串长度进行判断
判断字符串长度四种方法:
[1.echo “Str”|wc -l 2.变量字符串${#oldboy} 3.expr length “Str” 4.echo “Str”|awk ‘{print length($0)}” 5.echo “str”|wc -m]
判断字符串为空的三种方法:
[1. if [ “Str” = “” ] 2.if [ x”Str” = x ] 3.if [ -z “Str” ] ]
#!/bin/bash
for i in I am oldboy teacher welcome to oldboy training class
do
[ ${#i} -le 6 ] && echo $i
done
#!/bin/bash
for i in I am oldboy teacher welcome to oldboy training class
do
[ `echo $i|wc -L` -le 6 ] && echo $i
done
方法二:
#!/bin/bash
array=(I am oldboy teacher welcome to oldboy training class)
for((i=0;i<${#array[@]};i++))
do
#echo ${array[i]}
if [ `expr length “${array[i]}”` -le 3 ];then
echo ${array[i]}
fi
done
方法三:
echo “I am oldboy teacher welcome to oldboy training class”|awk ‘{for(i=1;i<=NF;i++) if(length($i)<=6 ) print $i}’
[awk有三种循环:while循环;for循环;special for循环
$ awk ‘{ i=1;while (i<=NF) {print NF,$i;i++}}’
$ awk ‘{for(i=1;i<=NF;i++) print NF,$i}’
{for ( x=3; x<=NF; x++) if ($x<0 ){print “Bottomed out!”; break }}
{for ( x=3; x<=NF; x++) if ($x==0){print “Get next item”; continue}} ]
3.用shell把文件(假设一共51行)特定行打印出来,比如第一行,第十一行,第二十一行……第五十一行
方法一:
for i in `seq 1 10 51`
do
sed -n “${i}p” /etc/services
done
方法二:
cat -n /etc/services|sed -n ‘1~10p’ [~表示步长,即间隔]
方法三:
#!/bin/bash
for((i=1;i<=52;i=i+10))
do
sed -n “${i}p” /etc/services
done
for ((i=1;i<=52;i=i+10))
do
sed -n -e “${i}p” -e ${i}= /etc/services
done
[sed -n “1p” 打印第一行内容;sed “1p” 打印第一行和全部内容 (添加-n与没有的区别)
sed -e的应用。只有当sed命令传递多个编辑命令式,才会使用到-e。比如:我想打印/tr/匹配行,并且打印匹配行所在的行号,此时存在多个sed参数,就要用到-e了。sed -n -e /tr/p -e /tr/= test2.sh]
方法四:cat /etc/services|awk ‘{if(NR%10==1) print $0}’

4.如何获取/etc/test.log文件夹权限-rw-r–r–(644),要求使用命令取得644的字样
方法一:
stat /etc/test.log|head -4|tail -1|cut -d “/” -f1|cut -d “0” -f2
方法二:
stat /etc/test.log|sed -n “4p”|awk -F “/” ‘{print $1}’|awk -F “(” ‘{print $2}’
方法三:
stat -c %a /etc/test.log %a 以8进制显示
[stat查看文件相关信息,包括访问时间,修改时间,状态时间
1、访问时间,读一次这个文件的内容,这个时间就会更新。比如对这个文件使用more命令。ls 、stat命令都不会修改文件的访问时间
2、修改时间,对文件内容修改一次,这个时间就会更新。比如vi后保存文件。ls -l列出的时间就是这个时间
3、状态改变时间。通过chmod命令更改一次文件属性,这个时间就会更新。查看文件的详细的状态、准确的修改时间等,可以通过stat命令
tail -n 输出最后n行,默认是10行 tail -f 不停地读取文件的最新内容,有监视文件的效果
]

5.计算你还有多少天几小时过生日(1.先让用户输入日期 2.比较现有日期)
方法一:
#!/bin/bash
echo “This program will try to calculate your birthday:”
echo “How many days about your demobilization date….”
read -p “Please input your demobilization date (YYYYMMDD ex>20050401):” date2
date_d=`echo $date2|grep ‘[0-9]\{8\}’`
if [ $date_d == “” ];then
echo “you input the wrong of date ….”
exit 1
fi
declare -i date_dem=`date –date=”$date2″ +%s`
declare -i date_now=`date +%s`
declare -i date_total_s=$(($date_dem-$date_now))
declare -i date_d=$(($date_total_s/60/60/24))
if [ “$date_total_s” -lt 0 ];then
echo “you had been demobilization before: “$((-1*$date_d))” ago”
else
declare -i date_h=$(($(($date_total_s-$date_d*60*60*24))/60/60))
echo “you will be demobilized after $date_d days and $date_h hours”
fi

6.用户输入一个目录,然后打印出这个目录下文件夹权限
#!/bin/bash
read -p “Please input a directory:” dir
if [ “$dir” == “” ] || [ ! -d “$dir” ];then
echo “Please input a right directory!!”
else
echo “the $dir is ok”
fi
filelist=`ls $dir`
for filename in $filelist
do
perm=””
test -x “$dir/$filename” && perm=”$perm executable”
test -w “$dir/$filename” && perm=”$perm writeable”
test -r “$dir/$filename” && perm=”$perm readable”
echo “The file $dir/$filename’s permission is $perm”
done

7.我么知道/etc/passwd 中以(:)来分隔,第一栏为账号名。请编写程序将/etc/passwd的第一栏取出,而且每一栏都以一行字符串”the $1 account is ‘root'”
#!/bin/bash
accounts=`awk -F ‘:’ ‘{print $1}’ /etc/passwd`
for member in $accounts
do
declare -i i
i=$i+1
echo “the $i account is $member”
done

8.打印根目录下,目录文件名超过10Mb文件
#!/bin/bash
dir=(`ls -l /|grep ‘^d’|grep -v “proc”|awk ‘{print $9}’`)
for i in ${dir[*]}
do
a=(`du -sk /$i|awk ‘{print $1}’`)
for m in $a
do
if [ $m -lt 10000 ]
then
echo “the $i than 10MB”
else
echo “the $i less 10MB”
fi
done
done

linux-shell面试题

分析apache日志,给出当日访问ip的降序列表。
一句话思路:分析ip就要提取ip,提取的办法除了awk,还有个东西叫cut。
cut  -d ” ”   -f1   /etc/httpd/log/access_log  |  sort  |  uniq  -c  |  sort  -nr
知识点:cut命令,sort将汇总相同内容,uniq -c合并重复内容,并给出重复次数。sort  -nr  使用数字排序,默认是ascii,并且是降序,默认是升序。
awk      ‘{sum[ip]++}END{for(var in sum)print ip sum[var]}’   /etc/httpd/log/access_log  | sort -k2 -nr
知识点:awk数据,sort -k2 -nr 降序数字排序就不说了,-k参数指定使用哪个列进行排序。默认是自然是第一列。
1、编写shell程序,实现自动删除50个账号的功能。账号名为stud1至stud50。
一句话思路:找出规律,循环解决
for((i=1;i<51;i++));do userdel -r stud$i ;done
知识点:for循环,当然是用while循环也是可以的,until也行。

2、某系统管理员需每天做一定的重复工作,请按照下列要求,编制一个解决方案:
(1)在下午4 :50删除/abc目录下的全部子目录和全部文件;
(2)从早8:00~下午6:00每小时读取/xyz目录下x1文件中每行第一个域的全部数据加入到/backup目录下的bak01.txt文件内;
(3)每逢星期一下午5:50将/data目录下的所有目录和文件归档并压缩为文件:backup.tar.gz;

一句话思路:主要考验管理员对于计划任务的熟悉程度
crontab -e
50 16 * * * rm -rf /abc/*
* 8-18/1 * * * awk ‘{print $1 > “/backup/bak01.txt”}’ /xyz/x1
50 17 * * 1 tar -czf backup.tar.gz /data

知识点:awk的输出重定向,当然用管道也是可以的。tar命令打包参数,这样做会有一个提示,只是去掉了目录不用理会。

3、gameser这个服务启动命令为./gameser服务,请写一个脚本,当服务宕掉,脚本自动拉起gameser服务。

一句话思路:进程管理

#!/bin/bash

while true;do

result=`ps aux | grep gameser | wc -l`

if [ $result -lt 2 ];then  ./gameser; fi

sleep 5
done

知识点:还可以使用pgrep命令。

4、linux crontab;请在3月23号21点18分的时候,重启服务器

一句话思路:计划任务+关机

crontab -e
18 21 23 3 * init 6

知识点:可能会延展提问到最安全的关机命令,“写缓存”sync 最好两遍,有人说三遍,其实四遍也行,要不干脆还是别关机了!

5、你想每天23:00运行xxxx.sh脚本。并自动进行日志分析。第2天上班的时候看到分析结果 给出你的部属方案

一句话思路:计划任务,日志分析

0 23 * * * sh ****.sh;err=$?;logger -p cron.err $err

知识点:第一个参数一定要写零,否则在定义的23点里每分钟都会执行。计划任务只有当报错的时候才会以邮件形式发送给用户,所以这里使用logger命令将消息发送给日志服务器,这里只是发送了命令返回值,你可以随意发送内容,看你喜欢了。

6、要求:运行脚本输入两个数得到如下结果:

#sh xxx.sh 2 3
**
***
*****

一句话思路:看到这个第一反应就是循环呗。

#!/bin/bash
line1=$1
line2=$2
let line3=$1+$2
while [ $line1 -gt 0 ];do
echo -n *
let line1=$line1-1
done
echo
while [ $line2 -gt 0 ];do
echo -n *
let line2=$line2-1
done
echo
while [ $line3 -gt 0 ];do
echo -n *
let line3=$line3-1
done
echo

知识点:如果你的第一反应是使用循环,那就进入一个死循环了,因为根本就没有规律。我们都知道,循环是依靠一定规律的。echo 的 -n参数。*在shell中是通配符,所以要加转义字符。(希望你能给出更好的解决方案!)

9、查找文件后缀是log的 三天前的文件删除

一句话思路:查找就一定是find

find / -name “*.log” -and -mtime +3 -exec rm -rf {} ;

知识点:-mtime  + 代表后面数字之外的,- 就是之内的。

10、写一个脚本将目录下大于100kb的文件移动到/tmp下

一句话思路:同上

find ./ -size +100k -exec mv {}  /tmp ;

知识点:-exec  {}  ; 标准写法,没有好办法,背吧。

11 、日志如下统计访问IP最多的前10个

192.168.0.6 – – [25/Nov/2010:13:55:10 +0800] “GET /cacti/images/auth_login.gif HTTP/1.1” 200 21265 “http://192.168.0.104/cacti/graph_view.php?action=tree&tree_id=2&leaf_id=8&page=3” “Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.1)”
192.168.0.6 – – [25/Nov/2010:13:55:14 +0800] “GET /favicon.ico HTTP/1.1” 404 287 “-” “Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.1)

这个题在前一篇中已经给出答案,这里就不再赘述。

http://7648853.blog.51cto.com/4990508/851407

12、过滤出当前目录下所有以字母(不区分大小写)开头的文件

一句话思路:过滤就是grep

ls | grep -P “^[a-zA-Z]”

ls | grep -P -i “^[a-z]”

知识点:正则表达式,使用-i参数让grep命令不区分大小写。

13、文件A.txt内容为”12:34:68″,只输出A.txt中的”34″

一句话思路:提取内容就是awk

awk  -F “:” ‘{print $2}’ A.txt

知识点:awk 域,-F参数指定分隔符,默认分隔符是空格。

14、用sed命令实现直接将文件B.TXT中的所有123替换成345

一句话思路:没思路了,人家都说了用sed

sed -i ‘s/123/456/g’ B.TXT

知识点:-i参数让sed修改文件,默认不修改源文件。题目中提到了所有字样,所以要使用g参数。

15、用sed修改文件mailbox.txt的20行的zhango为wang

一句话思路:命题作文sed,没有瞎想空间

sed -i ’20s/zhango/wang/’ mailbox.txt

知识点:上题是全局,这题规定了行。如果写成这样”/20/”,就是正则表达式了。

16、正则表达式,IP地址的匹配,写一下

一句话思路:遥想当年,web开发程序员面试不出意外的第一道题。

([0-9]{1,3}.){1,3}([0-9]){1,3}

知识点:正则表达式,写个简单的,这个答案不严谨,但考虑到只是面试,所以将就将就也能用。

17、写出命令。统计日志文件weblog.log中 今天14:00~15:00的记录条数(时间格式:2011-01-01—15:30:11)

一句话思路:第一反应,这个要用awk,分析统计嘛。可真要用awk麻烦就大了。

sum14=`grep -c “2011-01-01-14” weblog.log`
sum15=`grep -c “2011-01-01-15” weblog.log`
echo $[$sum14+$sum15]

知识点:grep命令-c参数,统计匹配的行数。shell中的数学计算。

18、求一组数的最大值和最小值

一句话思路:运维越来越像开发了,冒泡法都有了。越来越难混了,一个运维不看手册,要看算法了。

知识点:去看书吧,看算法的。

19、将当前目录所有文件扩展名改为log

一句话思路:如果你的第一反应是使用find命令,那么恭喜你,你中了敌人的奸计,不是不能实现,是很麻烦。

for file in `ls ./ | grep -P “(.*)(..*)”`;do  echo $file | mv $file `sed -r ‘s#(.*)(..*)#1.log#’`; done

for file in `ls ./ | grep -P “(.*)(..*)”`;do  echo $file | mv $file `echo ${file%.**}`.log; done

知识点:第一个方法中使用了sed,第二个方法中使用了字符操作,#从前向后数,%从后向前数。其实说白了,就是为了拼凑出 mv 参数1 参数2。其实很多时候,编写shell脚本的时候要学会反向推导,逆向思考。

还有一种方法是使用cut命令,但如果遇到文件有两个扩展名的情况下就会出现问题。redhat as4 安装完成后,在root目录下会生成install.log  install.log.syslog这两个文件,如果使用cut就会出现错误。具体原因在这里就不说了。运维嘛,需要的是严谨!

20、用shell在/usr/local下 建立20个子目录 xunlei1-xunlei20,再在这个子目录下分别建255个子目录dir1-dir255,再在255个子目录下创建10000个文件xunlei1.html-xunlei10000.html

一句话思路:这有啥,{}大括号呗。

mkdir -p /usr/loca/xunlie{1..20}/dir{1..255}/

touch   /usr/loca/xunlie{1..20}/dir{1..255}/xunlei{1..10000}.html

知识点:如果你就这么写上去,那你又中计了。为什么呢,因为超过了shell命令参数的最大限制。shell中参数的限制是:5452。所以要分着写。

linux(centos)发送带附件的邮件

前言:用程序发送邮件有3种方式,分别是:

1.模拟http请求邮件服务商网页实现邮件的发送

2.如果邮件服务商开通了smtp服务,那么可以通过smtp协议通过邮件代理服务商发送邮件

3.自己部署邮件服务器,直接在邮件服务器上发送邮件

 

前边两种方式相对简单,其实都可以理解为使用他人的邮件服务器发送邮件,相对来讲会过于依赖第三方的邮件服务器提供的服务,并且在发送邮件时邮件会 先进邮件代理服务器的邮箱,再转发至收件人的邮箱,邮件中转过慢,所以在条件允许的情况下,我更喜欢采用我自己的邮件服务器发送邮件;

 

今天,我就对第三种邮件发送方式(linux(centos)下shell命令发送带附件的邮件)做一下总结

 

linux下邮件发送命令我常用的主要有mail,sendmail,mutt;

 

1.mail命令

普通正文邮件发送命令格式:

1)mail -s “邮件主题”  收件人@邮件服务商.com  < 邮件正文内容.txt(此方式需要把邮件正文内容先保存到 邮件正文内容.txt)

2)步骤一:键入 mail -s “邮件主题”  收件人@邮件服务商.com

步骤二:点击enter回车按钮

步骤三:输入邮件正文内容

步骤四:点击enter回车按钮

步骤五:同时按住ctrl+d按钮

3)echo  邮件正文内容 | mail -s “邮件主题”  收件人@邮件服务商.com

 

 

带附件的邮件发送方式:

在普通mail 命令后边加 -a 文件名

例子“ mail -s “你好” -a a.txt xxx@qq.com”

 

 

2.sendmail

普通邮件发送方式同mail类似

带附件的邮件发送方式:

写道
1、用uuencode 将附件编码为文本形式
uuencode 附件 希望在邮件中使用的附件名 > 附件文本文件
2、连接邮件正文文件和附件文本文件
cat 邮件正文文件 附件文本文件 > 正文附件联合文件
3、发送该邮件
sendmail -s “你想使用的邮件标题” 收信人email地址 < 正文附件联合文件
示例:
我的邮件正文文件是 message.txt,想发送的附件名字是 attachment.tar.gz,附件文本文件取名为attachment.txt,正文附件联合文件取名为combined.txt,以“测试”为邮件标题发信给Sam@test.com
uuencode attachment.tar.gz attachment.tar.gz > attachment.txt
cat message.txt attachment.txt > combined.txt
sendmail -s “测试’ Sam@test.com < combined.txt

 

 

3.mutt

写道
Muttmutt_button.gif是个功能强大的email 程序,引用一段别人的话:

“你也许听说过这句话?这不是危言耸听,我还没有遇到一个令我满意的 email 程序,直到我遇到 mutt。它不是图形界面的,但是它非常强大和方便。我曾经把它忽略,但是后来我发现其它 email 程序都有某种我不喜欢的怪毛病。最后我选择了 Mutt。”

我在这里只想介绍一下怎样使用Mutt在Linux/Unix下发送邮件:
以下是命令示范:

[root@jumper root]# mutt -s “this is a test mail” eygle@itpub.net -a a.c < /etc/hosts

其中:
s—主题
a—附件
最后追加的是邮件内容

这样就可以发送了。

如果想要了解更多关于Mutt的内容,可以访问http://www.mutt.org

shell 发送邮件

bin/mail(bin/mailx)默认使用本地sendmail发送邮件,本地的机器必须安装并启动Sendmail服务,配置比较麻烦,不稳定。

下文通过修改配置文件可以使用外部SMTP服务器来发送邮件。

以网易邮箱为例。

1、vim  /etc/mail.rc #( /etc/nail.rc),追加如下文字

set from=from@163.com

set smtp=smtp.163.com

set smtp-auth-user=from@163.com

set smtp-auth-password=aaaa

set smtp-auth=login

说明:

from是发送的邮件地址

smtp是发生的外部smtp服务器的地址

smtp-auth-user是外部smtp服务器认证的用户名

smtp-auth-password是外部smtp服务器认证的用户密码

smtp-auth是邮件认证的方式

配置后执行如下命令:

cat context.txt| mail -s “tes the smtp mail” toooo@163.com

userfasdf@163com是收件人地址,content.txt里面是邮件正文.

LINUX下通过外部SMTP发邮件

至于sentmail和postfix的配置有多么麻烦老衲在这里就不多废话了…反正老衲是配置了N个小时,最终弄的头晕眼花也没弄好…

下面的方法可以让你完全摆脱这两个工具…当然,你要是想做邮件服务器的话就令当别论了…你要是只想让服务器自动发个邮件什么的,用下面的就行了

 

通常的做法都是,关闭本机的sendmail服务或者postfix服务,
复制代码
#执行下面的命令,各位大侠都对号入座吧
#sendmial
service sendmail stop
chkconfig sendmail off
#postfix
service postfix stop
chkconfig postfix off

#再狠一点就直接卸载吧..
yum remove sendmail
yum remove postfix
复制代码

 

然后修改/etc/mail.rc,增加一下类似N行,指定外部的smtp服务器地址、帐号密码等。
1 # vi /etc/mail.rc  
2  set from=123456@qq.com
3  set smtp=smtp.qq.com  
4  set smtp-auth-user=123456
5  set smtp-auth-password=sbsbsbsb
6  set smtp-auth=login

 

然后通过命令来发送邮件
echo  hello word | mail -s " title" 123456@qq.com

 

可是发现在RHEL6运行是没有问题,在RHEL5下,mail命令始终是调用本地的sendmail服务来发送邮件的。
到底RHEL6和RHEL5下的mail和mailx又有着什么关系呢?
RHEL6下
mail  链接到 mailx 命令,mailx版本为12.4
# rpm -qa|grep mailx
mailx-12.4-6.el6.x86_64
# ll /bin/mail*
lrwxrwxrwx. 1 root root      5  7月 22 2011 /bin/mail -> mailx
-rwxr-xr-x. 1 root root 390424  2月 16 2010 /bin/mailx
# mail -V
12.4 7/29/08
RHEL5下,则发现了一些不同
mailx  链接到  mail 命令,mailx版本为8.1
# rpm -qa|grep mailx
mailx-8.1.1-44.2.2
# ll /bin/mail*
-rwxr-xr-x 1 root mail 84856 Jun  6  2007 /bin/mail
lrwxrwxrwx 1 root root     4 Apr 12 18:03 /bin/mailx -> mail
# mail -V     此处运行就会出错,没有-V这个参数
也就是说,在RHEL6\5下,运行mail 和mailx,实际上都是一个命令,而mail版本不同,导致了RHEL5下mail命令无法调用外部SMTP服务器。
安装mailx新版本可解决此问题。
下载地址:
代开这个网站。自己选一个下载地址
1 http://www.filewatcher.com/m/mailx-12.4.tar.bz2.271482.0.0.html

下载后

 # tar jxvf mailx-12.4.tar.bz2  
 # cd mailx-12.4  
 # make  
 # make install UCBINSTALL=/usr/bin/install

查看mailx程序默认安装位置、及版本

 # whereis mailx  
 mailx: /usr/local/bin/mailx /usr/share/man/man1p/mailx.1p.gz  
 # mailx -V  
 12.4 7/29/08
安装后的mailx使用的是 /etc/nail.rc 配置,不是 /etc/mail.rc 这个需要注意下。vi编辑,按下G  ,然后在行尾添加如下N行
    # vi /etc/nail.rc  (看出亮点了吗?)
 2  set from=123456@qq.com
 3  set smtp=smtp.qq.com  
 4  set smtp-auth-user=123456
 5  set smtp-auth-password=sbsbsbsb
 6  set smtp-auth=login

然后通过命令来发送邮件

echo  hello word | mailx -v -s " title" 123456@qq.com

 

就收到邮件了…. 哥比较懒,就不给你截图了…反正我是收到了。
复制代码
成功发送的话,就可以看到类似的提示
 235 2.7.0 Authentication successful  
 >>> MAIL FROM:<demo@qq.com>  
 250 2.1.0 Ok  
 >>> RCPT TO:<xxxxx@qq.com>  
 250 2.1.5 Ok  
 >>> DATA  
 354 End data with <CR><LF>.<CR><LF>  
 >>> .  
 250 2.0.0 Ok: queued as 9291963494  
 >>> QUIT  
 221 2.0.0 Bye

SED单行脚本参考

SED单行脚本快速参考(Unix 流编辑器)                       2005年12月29日

英文标题:USEFUL ONE-LINE SCRIPTS FOR SED (Unix stream editor)
原标题:HANDY ONE-LINERS FOR SED (Unix stream editor)

整理:Eric Pement  - 电邮:pemente[at]northpark[dot]edu         版本5.5
译者:Joe Hong     - 电邮:hq00e[at]126[dot]com

在以下地址可找到本文档的最新(英文)版本:
   http://sed.sourceforge.net/sed1line.txt
   http://www.pement.org/sed/sed1line.txt

其他语言版本:
  中文          - http://sed.sourceforge.net/sed1line_zh-CN.html
  捷克语        - http://sed.sourceforge.net/sed1line_cz.html
  荷语          - http://sed.sourceforge.net/sed1line_nl.html
  法语          - http://sed.sourceforge.net/sed1line_fr.html
  德语          - http://sed.sourceforge.net/sed1line_de.html

  葡语          - http://sed.sourceforge.net/sed1line_pt-BR.html


文本间隔:
--------

 # 在每一行后面增加一空行
 sed G

 # 将原来的所有空行删除并在每一行后面增加一空行。
 # 这样在输出的文本中每一行后面将有且只有一空行。
 sed '/^$/d;G'

 # 在每一行后面增加两行空行
 sed 'G;G'

 # 将第一个脚本所产生的所有空行删除(即删除所有偶数行)
 sed 'n;d'

 # 在匹配式样“regex”的行之前插入一空行
 sed '/regex/{x;p;x;}'

 # 在匹配式样“regex”的行之后插入一空行
 sed '/regex/G'

 # 在匹配式样“regex”的行之前和之后各插入一空行
 sed '/regex/{x;p;x;G;}'

编号:
--------

 # 为文件中的每一行进行编号(简单的左对齐方式)。这里使用了“制表符”
 # (tab,见本文末尾关于'\t'的用法的描述)而不是空格来对齐边缘。
 sed = filename | sed 'N;s/\n/\t/'

 # 对文件中的所有行编号(行号在左,文字右端对齐)。
 sed = filename | sed 'N; s/^/     /; s/ *\(.\{6,\}\)\n/\1  /'

 # 对文件中的所有行编号,但只显示非空白行的行号。
 sed '/./=' filename | sed '/./N; s/\n/ /'

 # 计算行数 (模拟 "wc -l")
 sed -n '$='

文本转换和替代:
--------

 # Unix环境:转换DOS的新行符(CR/LF)为Unix格式。
 sed 's/.$//'                     # 假设所有行以CR/LF结束
 sed 's/^M$//'                    # 在bash/tcsh中,将按Ctrl-M改为按Ctrl-V
 sed 's/\x0D$//'                  # ssed、gsed 3.02.80,及更高版本

 # Unix环境:转换Unix的新行符(LF)为DOS格式。
 sed "s/$/`echo -e \\\r`/"        # 在ksh下所使用的命令
 sed 's/$'"/`echo \\\r`/"         # 在bash下所使用的命令
 sed "s/$/`echo \\\r`/"           # 在zsh下所使用的命令
 sed 's/$/\r/'                    # gsed 3.02.80 及更高版本

 # DOS环境:转换Unix新行符(LF)为DOS格式。
 sed "s/$//"                      # 方法 1
 sed -n p                         # 方法 2

 # DOS环境:转换DOS新行符(CR/LF)为Unix格式。
 # 下面的脚本只对UnxUtils sed 4.0.7 及更高版本有效。要识别UnxUtils版本的
 #  sed可以通过其特有的“--text”选项。你可以使用帮助选项(“--help”)看
 # 其中有无一个“--text”项以此来判断所使用的是否是UnxUtils版本。其它DOS
 # 版本的的sed则无法进行这一转换。但可以用“tr”来实现这一转换。
 sed "s/\r//" infile >outfile     # UnxUtils sed v4.0.7 或更高版本
 tr -d \r <infile >outfile        # GNU tr 1.22 或更高版本

 # 将每一行前导的“空白字符”(空格,制表符)删除
 # 使之左对齐
 sed 's/^[ \t]*//'                # 见本文末尾关于'\t'用法的描述

 # 将每一行拖尾的“空白字符”(空格,制表符)删除
 sed 's/[ \t]*$//'                # 见本文末尾关于'\t'用法的描述

 # 将每一行中的前导和拖尾的空白字符删除
 sed 's/^[ \t]*//;s/[ \t]*$//'

 # 在每一行开头处插入5个空格(使全文向右移动5个字符的位置)
 sed 's/^/     /'

 # 以79个字符为宽度,将所有文本右对齐
 sed -e :a -e 's/^.\{1,78\}$/ &/;ta'  # 78个字符外加最后的一个空格

 # 以79个字符为宽度,使所有文本居中。在方法1中,为了让文本居中每一行的前
 # 头和后头都填充了空格。 在方法2中,在居中文本的过程中只在文本的前面填充
 # 空格,并且最终这些空格将有一半会被删除。此外每一行的后头并未填充空格。
 sed  -e :a -e 's/^.\{1,77\}$/ & /;ta'                     # 方法1
 sed  -e :a -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/'  # 方法2

 # 在每一行中查找字串“foo”,并将找到的“foo”替换为“bar”
 sed 's/foo/bar/'                 # 只替换每一行中的第一个“foo”字串
 sed 's/foo/bar/4'                # 只替换每一行中的第四个“foo”字串
 sed 's/foo/bar/g'                # 将每一行中的所有“foo”都换成“bar”
 sed 's/\(.*\)foo\(.*foo\)/\1bar\2/' # 替换倒数第二个“foo”
 sed 's/\(.*\)foo/\1bar/'            # 替换最后一个“foo”

 # 只在行中出现字串“baz”的情况下将“foo”替换成“bar”
 sed '/baz/s/foo/bar/g'

 # 将“foo”替换成“bar”,并且只在行中未出现字串“baz”的情况下替换
 sed '/baz/!s/foo/bar/g'

 # 不管是“scarlet”“ruby”还是“puce”,一律换成“red”
 sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g'  #对多数的sed都有效
 gsed 's/scarlet\|ruby\|puce/red/g'               # 只对GNU sed有效

 # 倒置所有行,第一行成为最后一行,依次类推(模拟“tac”)。
 # 由于某些原因,使用下面命令时HHsed v1.5会将文件中的空行删除
 sed '1!G;h;$!d'               # 方法1
 sed -n '1!G;h;$p'             # 方法2

 # 将行中的字符逆序排列,第一个字成为最后一字,……(模拟“rev”)
 sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'

 # 将每两行连接成一行(类似“paste”)
 sed '$!N;s/\n/ /'

 # 如果当前行以反斜杠“\”结束,则将下一行并到当前行末尾
 # 并去掉原来行尾的反斜杠
 sed -e :a -e '/\\$/N; s/\\\n//; ta'

 # 如果当前行以等号开头,将当前行并到上一行末尾
 # 并以单个空格代替原来行头的“=”
 sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'

 # 为数字字串增加逗号分隔符号,将“1234567”改为“1,234,567”
 gsed ':a;s/\B[0-9]\{3\}\>/,&/;ta'                     # GNU sed
 sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'  # 其他sed

 # 为带有小数点和负号的数值增加逗号分隔符(GNU sed)
 gsed -r ':a;s/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g;ta'

 # 在每5行后增加一空白行 (在第5,10,15,20,等行后增加一空白行)
 gsed '0~5G'                      # 只对GNU sed有效
 sed 'n;n;n;n;G;'                 # 其他sed

选择性地显示特定行:
--------

 # 显示文件中的前10行 (模拟“head”的行为)
 sed 10q

 # 显示文件中的第一行 (模拟“head -1”命令)
 sed q

 # 显示文件中的最后10行 (模拟“tail”)
 sed -e :a -e '$q;N;11,$D;ba'

 # 显示文件中的最后2行(模拟“tail -2”命令)
 sed '$!N;$!D'

 # 显示文件中的最后一行(模拟“tail -1”)
 sed '$!d'                        # 方法1
 sed -n '$p'                      # 方法2

 # 显示文件中的倒数第二行
 sed -e '$!{h;d;}' -e x              # 当文件中只有一行时,输入空行
 sed -e '1{$q;}' -e '$!{h;d;}' -e x  # 当文件中只有一行时,显示该行
 sed -e '1{$d;}' -e '$!{h;d;}' -e x  # 当文件中只有一行时,不输出

 # 只显示匹配正则表达式的行(模拟“grep”)
 sed -n '/regexp/p'               # 方法1
 sed '/regexp/!d'                 # 方法2

 # 只显示“不”匹配正则表达式的行(模拟“grep -v”)
 sed -n '/regexp/!p'              # 方法1,与前面的命令相对应
 sed '/regexp/d'                  # 方法2,类似的语法

 # 查找“regexp”并将匹配行的上一行显示出来,但并不显示匹配行
 sed -n '/regexp/{g;1!p;};h'

 # 查找“regexp”并将匹配行的下一行显示出来,但并不显示匹配行
 sed -n '/regexp/{n;p;}'

 # 显示包含“regexp”的行及其前后行,并在第一行之前加上“regexp”所
 # 在行的行号 (类似“grep -A1 -B1”)
 sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h

 # 显示包含“AAA”、“BBB”或“CCC”的行(任意次序)
 sed '/AAA/!d; /BBB/!d; /CCC/!d'  # 字串的次序不影响结果

 # 显示包含“AAA”、“BBB”和“CCC”的行(固定次序)
 sed '/AAA.*BBB.*CCC/!d'

 # 显示包含“AAA”“BBB”或“CCC”的行 (模拟“egrep”)
 sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d    # 多数sed
 gsed '/AAA\|BBB\|CCC/!d'                        # 对GNU sed有效

 # 显示包含“AAA”的段落 (段落间以空行分隔)
 # HHsed v1.5 必须在“x;”后加入“G;”,接下来的3个脚本都是这样
 sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'

 # 显示包含“AAA”“BBB”和“CCC”三个字串的段落 (任意次序)
 sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'

 # 显示包含“AAA”、“BBB”、“CCC”三者中任一字串的段落 (任意次序)
 sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
 gsed '/./{H;$!d;};x;/AAA\|BBB\|CCC/b;d'         # 只对GNU sed有效

 # 显示包含65个或以上字符的行
 sed -n '/^.\{65\}/p'

 # 显示包含65个以下字符的行
 sed -n '/^.\{65\}/!p'            # 方法1,与上面的脚本相对应
 sed '/^.\{65\}/d'                # 方法2,更简便一点的方法

 # 显示部分文本——从包含正则表达式的行开始到最后一行结束
 sed -n '/regexp/,$p'

 # 显示部分文本——指定行号范围(从第8至第12行,含8和12行)
 sed -n '8,12p'                   # 方法1
 sed '8,12!d'                     # 方法2

 # 显示第52行
 sed -n '52p'                     # 方法1
 sed '52!d'                       # 方法2
 sed '52q;d'                      # 方法3, 处理大文件时更有效率

 # 从第3行开始,每7行显示一次    
 gsed -n '3~7p'                   # 只对GNU sed有效
 sed -n '3,${p;n;n;n;n;n;n;}'     # 其他sed

 # 显示两个正则表达式之间的文本(包含)
 sed -n '/Iowa/,/Montana/p'       # 区分大小写方式

选择性地删除特定行:
--------

 # 显示通篇文档,除了两个正则表达式之间的内容
 sed '/Iowa/,/Montana/d'

 # 删除文件中相邻的重复行(模拟“uniq”)
 # 只保留重复行中的第一行,其他行删除
 sed '$!N; /^\(.*\)\n\1$/!P; D'

 # 删除文件中的重复行,不管有无相邻。注意hold space所能支持的缓存
 # 大小,或者使用GNU sed。
 sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'

 # 删除除重复行外的所有行(模拟“uniq -d”)
 sed '$!N; s/^\(.*\)\n\1$/\1/; t; D'

 # 删除文件中开头的10行
 sed '1,10d'

 # 删除文件中的最后一行
 sed '$d'

 # 删除文件中的最后两行
 sed 'N;$!P;$!D;$d'

 # 删除文件中的最后10行
 sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # 方法1
 sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # 方法2

 # 删除8的倍数行
 gsed '0~8d'                           # 只对GNU sed有效
 sed 'n;n;n;n;n;n;n;d;'                # 其他sed

 # 删除匹配式样的行
 sed '/pattern/d'                      # 删除含pattern的行。当然pattern
                                       # 可以换成任何有效的正则表达式

 # 删除文件中的所有空行(与“grep '.' ”效果相同)
 sed '/^$/d'                           # 方法1
 sed '/./!d'                           # 方法2

 # 只保留多个相邻空行的第一行。并且删除文件顶部和尾部的空行。
 # (模拟“cat -s”)
 sed '/./,/^$/!d'        #方法1,删除文件顶部的空行,允许尾部保留一空行
 sed '/^$/N;/\n$/D'      #方法2,允许顶部保留一空行,尾部不留空行

 # 只保留多个相邻空行的前两行。
 sed '/^$/N;/\n$/N;//D'

 # 删除文件顶部的所有空行
 sed '/./,$!d'

 # 删除文件尾部的所有空行
 sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'  # 对所有sed有效
 sed -e :a -e '/^\n*$/N;/\n$/ba'        # 同上,但只对 gsed 3.02.*有效

 # 删除每个段落的最后一行
 sed -n '/^$/{p;h;};/./{x;/./p;}'

特殊应用:
--------

 # 移除手册页(man page)中的nroff标记。在Unix System V或bash shell下使
 # 用'echo'命令时可能需要加上 -e 选项。
 sed "s/.`echo \\\b`//g"    # 外层的双括号是必须的(Unix环境)
 sed 's/.^H//g'             # 在bash或tcsh中, 按 Ctrl-V 再按 Ctrl-H
 sed 's/.\x08//g'           # sed 1.5,GNU sed,ssed所使用的十六进制的表示方法

 # 提取新闻组或 e-mail 的邮件头
 sed '/^$/q'                # 删除第一行空行后的所有内容

 # 提取新闻组或 e-mail 的正文部分
 sed '1,/^$/d'              # 删除第一行空行之前的所有内容

 # 从邮件头提取“Subject”(标题栏字段),并移除开头的“Subject:”字样
 sed '/^Subject: */!d; s///;q'

 # 从邮件头获得回复地址
 sed '/^Reply-To:/q; /^From:/h; /./d;g;q'

 # 获取邮件地址。在上一个脚本所产生的那一行邮件头的基础上进一步的将非电邮
 # 地址的部分剃除。(见上一脚本)
 sed 's/ *(.*)//; s/>.*//; s/.*[:<] *//'

 # 在每一行开头加上一个尖括号和空格(引用信息)
 sed 's/^/> /'

 # 将每一行开头处的尖括号和空格删除(解除引用)
 sed 's/^> //'

 # 移除大部分的HTML标签(包括跨行标签)
 sed -e :a -e 's/<[^>]*>//g;/</N;//ba'

 # 将分成多卷的uuencode文件解码。移除文件头信息,只保留uuencode编码部分。
 # 文件必须以特定顺序传给sed。下面第一种版本的脚本可以直接在命令行下输入;
 # 第二种版本则可以放入一个带执行权限的shell脚本中。(由Rahul Dhesi的一
 # 个脚本修改而来。)
 sed '/^end/,/^begin/d' file1 file2 ... fileX | uudecode   # vers. 1
 sed '/^end/,/^begin/d' "$@" | uudecode                    # vers. 2

 # 将文件中的段落以字母顺序排序。段落间以(一行或多行)空行分隔。GNU sed使用
 # 字元“\v”来表示垂直制表符,这里用它来作为换行符的占位符——当然你也可以
 # 用其他未在文件中使用的字符来代替它。
 sed '/./{H;d;};x;s/\n/={NL}=/g' file | sort | sed '1s/={NL}=//;s/={NL}=/\n/g'
 gsed '/./{H;d};x;y/\n/\v/' file | sort | sed '1s/\v//;y/\v/\n/'

 # 分别压缩每个.TXT文件,压缩后删除原来的文件并将压缩后的.ZIP文件
 # 命名为与原来相同的名字(只是扩展名不同)。(DOS环境:“dir /b”
 # 显示不带路径的文件名)。
 echo @echo off >zipup.bat
 dir /b *.txt | sed "s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/" >>zipup.bat


使用SED:Sed接受一个或多个编辑命令,并且每读入一行后就依次应用这些命令。
当读入第一行输入后,sed对其应用所有的命令,然后将结果输出。接着再读入第二
行输入,对其应用所有的命令……并重复这个过程。上一个例子中sed由标准输入设
备(即命令解释器,通常是以管道输入的形式)获得输入。在命令行给出一个或多
个文件名作为参数时,这些文件取代标准输入设备成为sed的输入。sed的输出将被
送到标准输出(显示器)。因此:

 cat filename | sed '10q'         # 使用管道输入
 sed '10q' filename               # 同样效果,但不使用管道输入
 sed '10q' filename > newfile     # 将输出转移(重定向)到磁盘上

要了解sed命令的使用说明,包括如何通过脚本文件(而非从命令行)来使用这些命
令,请参阅《sed & awk》第二版,作者Dale Dougherty和Arnold Robbins
(O'Reilly,1997;http://www.ora.com),《UNIX Text Processing》,作者
Dale Dougherty和Tim O'Reilly(Hayden Books,1987)或者是Mike Arst写的教
程——压缩包的名称是“U-SEDIT2.ZIP”(在许多站点上都找得到)。要发掘sed
的潜力,则必须对“正则表达式”有足够的理解。正则表达式的资料可以看
《Mastering Regular Expressions》作者Jeffrey Friedl(O'reilly 1997)。
Unix系统所提供的手册页(“man”)也会有所帮助(试一下这些命令
“man sed”、“man regexp”,或者看“man ed”中关于正则表达式的部分),但
手册提供的信息比较“抽象”——这也是它一直为人所诟病的。不过,它本来就不
是用来教初学者如何使用sed或正则表达式的教材,而只是为那些熟悉这些工具的人
提供的一些文本参考。

括号语法:前面的例子对sed命令基本上都使用单引号('...')而非双引号
("...")这是因为sed通常是在Unix平台上使用。单引号下,Unix的shell(命令
解释器)不会对美元符($)和后引号(`...`)进行解释和执行。而在双引号下
美元符会被展开为变量或参数的值,后引号中的命令被执行并以输出的结果代替
后引号中的内容。而在“csh”及其衍生的shell中使用感叹号(!)时需要在其前
面加上转义用的反斜杠(就像这样:\!)以保证上面所使用的例子能正常运行
(包括使用单引号的情况下)。DOS版本的Sed则一律使用双引号("...")而不是
引号来圈起命令。

'\t'的用法:为了使本文保持行文简洁,我们在脚本中使用'\t'来表示一个制表
符。但是现在大部分版本的sed还不能识别'\t'的简写方式,因此当在命令行中为
脚本输入制表符时,你应该直接按TAB键来输入制表符而不是输入'\t'。下列的工
具软件都支持'\t'做为一个正则表达式的字元来表示制表符:awk、perl、HHsed、
sedmod以及GNU sed v3.02.80。

不同版本的SED:不同的版本间的sed会有些不同之处,可以想象它们之间在语法上
会有差异。具体而言,它们中大部分不支持在编辑命令中间使用标签(:name)或分
支命令(b,t),除非是放在那些的末尾。这篇文档中我们尽量选用了可移植性较高
的语法,以使大多数版本的sed的用户都能使用这些脚本。不过GNU版本的sed允许使
用更简洁的语法。想像一下当读者看到一个很长的命令时的心情:

   sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d

好消息是GNU sed能让命令更紧凑:

   sed '/AAA/b;/BBB/b;/CCC/b;d'      # 甚至可以写成
   sed '/AAA\|BBB\|CCC/b;d'

此外,请注意虽然许多版本的sed接受象“/one/ s/RE1/RE2/”这种在's'前带有空
格的命令,但这些版本中有些却不接受这样的命令:“/one/! s/RE1/RE2/”。这时
只需要把中间的空格去掉就行了。

速度优化:当由于某种原因(比如输入文件较大、处理器或硬盘较慢等)需要提高
命令执行速度时,可以考虑在替换命令(“s/.../.../”)前面加上地址表达式来
提高速度。举例来说:

   sed 's/foo/bar/g' filename         # 标准替换命令
   sed '/foo/ s/foo/bar/g' filename   # 速度更快
   sed '/foo/ s//bar/g' filename      # 简写形式

当只需要显示文件的前面的部分或需要删除后面的内容时,可以在脚本中使用“q”
命令(退出命令)。在处理大的文件时,这会节省大量时间。因此:

   sed -n '45,50p' filename           # 显示第45到50行
   sed -n '51q;45,50p' filename       # 一样,但快得多

如果你有其他的单行脚本想与大家分享或者你发现了本文档中错误的地方,请发电
子邮件给本文档的作者(Eric Pement)。邮件中请记得提供你所使用的sed版本、 
该sed所运行的操作系统及对问题的适当描述。本文所指的单行脚本指命令行的长
度在65个字符或65个以下的sed脚本〔译注1〕。本文档的各种脚本是由以下所列作
者所写或提供:

 Al Aab                               # 建立了“seders”邮件列表
 Edgar Allen                          # 许多方面
 Yiorgos Adamopoulos                  # 许多方面
 Dale Dougherty                       # 《sed & awk》作者
 Carlos Duarte                        # 《do it with sed》作者
 Eric Pement                          # 本文档的作者
 Ken Pizzini                          # GNU sed v3.02 的作者
 S.G. Ravenhall                       # 去html标签脚本
 Greg Ubben                           # 有诸多贡献并提供了许多帮助
-------------------------------------------------------------------------

译注1:大部分情况下,sed脚本无论多长都能写成单行的形式(通过`-e'选项和`;'
号)——只要命令解释器支持,所以这里说的单行脚本除了能写成一行还对长度有
所限制。因为这些单行脚本的意义不在于它们是以单行的形式出现。而是让用户能
方便地在命令行中使用这些紧凑的脚本才是其意义所在。