存档

‘Shell脚本编程’ 分类的存档

/dev/null 2>&1 解释

2016年12月11日 评论已被关闭

/dev/null 2>&1 解释
http://blog.sina.com.cn/s/blog_62a9b1bb0100shg4.html
原文地址:/dev/null 2>&1 解释作者:Learn_linux

crontab内容 :50 18 5-30 * * /asia/script/myscript.sh 1> /dev/null 2>&1
其中 1> /dev/null 2>&1是什么意思??
dev/null 为系统垃圾箱
&为后台运行
但是 myscript 后面的1 和 /null后面的2 还有 &后面的1是什么意思?

1代表标准输出,2代表错误信息输出.
1>/dev/null 就是指将标准输出定向到空设备,
2>&1,的意思是将错误输出定向到和1一样的输出设备,也同样是空.
换句话说,就是不显示该程序执行过程中的任何信息
cmd >a 2>a 和 cmd >a 2>&1 为什么不同?

cmd >a 2>a :stdout和stderr都直接送往文件 a ,a文件会被打开两遍,由此导致stdout和stderr互相覆盖。

cmd >a 2>&1 :stdout直接送往文件a ,stderr是继承了FD1的管道之后,再被送往文件a 。a文件只被打开一遍,就是FD1将其打开。

解决 debian TAB 键不能自动补全命令的原因

2016年12月8日 评论已被关闭

解决 debian TAB 键不能自动补全命令的原因

http://phpquan.com/lamp/linux/debian-tab-apt-get/

一般情况,命令行输入 sudo apt-get ins 按 tab ,它后面会自动补全为 install 如果右面写了包的名的一部分,按 tab 它也会自动完成或列出候选的,这次装了个 debian 5 突然不好使了

首先确认是否安装了 自动补全的插件,输入

apt-get install bash-completion

问了一圈都不知道,后来还是在老外的 blog 上找到答案:

即 在 .bash_profile 里加

if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi

就 ok 了

链接:http://gumelta.com/add-bash-completion-in-debian.php

完整 copy 下来吧:

Add Bash Completion In Debian

ash completion is a useful tool for completion of file paths, commands etc. By default it is enabled on Ubuntu but not on Debian. With two simple steps it can also be enabled on Debian.

1. Install bash-completion

First of all we need the install the according package:

apt-get install bash-completion

2. Add it to the bash profile

Either edit the ~/.bash_profile file to enable it only for a given user or edit /etc/profile to add it system-wide. Add the following code:
if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
3. Try it

In order for it to work you have to log out and relogin and then you can make use of bash completion the usual way. E.g. issue:
apt-g

and then press the TAB key once and the command will be completed to apt-get. Or issue this:
apt

and then press TAB key twice. You can also try with
apt-get install apa

and then press TAB key once to complete as far as possible and a second time to list all options.

转自:http://hi.baidu.com/liheng_2009/

Debian 8 Tab命令无法自动补全

2016年12月8日 评论已被关闭

Debian 8 Tab命令无法自动补全
http://blog.csdn.net/langqingzailanda/article/details/50248661
在Dibian 8中使用useradd命令创建的用户默认使用dash,Tab无法自动补全

需要修改/etc/passwd中用户的属性,例如

tmp:x:1003:1003::/home/tmp:/bin/sh 修改为
tmp:x:1003:1003::/home/tmp:/bin/bash

或者在创建时加入相应参数

useradd -s /bin/bash <username>

系统dash配置

sudo dpkg-reconfigure dash
选no,就可以更改默认shell环境

另外,xfce桌面快捷键会占中tab键导致无法补全

可以按照下面链接中的方法进行解决
http://blog.163.com/thinki_cao/blog/static/83944875201303081111436/

解决 debian TAB 键不能自动补全命令的原因

2016年12月8日 评论已被关闭

解决 debian TAB 键不能自动补全命令的原因
https://my.oschina.net/yygh/blog/405403
一般情况,命令行输入 sudo apt-get ins 按 tab ,它后面会自动补全为 install 如果右面写了包的名的一部分,按 tab 它也会自动完成或列出候选的,这次装了个 debian 5 突然不好使了

首先确认是否安装了 自动补全的插件,输入

apt-get install bash-completion

问了一圈都不知道,后来还是在老外的 blog 上找到答案:

即 在 .bash_profile 里加

if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi

就 ok 了

Linux Shell 按Tab键不能补全

2016年12月8日 评论已被关闭

Linux Shell 按Tab键不能补全
http://www.cnblogs.com/ainubis/p/3990005.html
今天碰到一个问题git 后面的参数用Tab键无法补全 例如git c_

在网上找了半天找到答案如下
今天在Linux上用useradd新增用户的时候,发现使用新增的用户登陆的时候,在Shell里面不能使用Tab键补全命令,按上下键也不能切换历史命令,出现乱码的现象。Root用户是OK的。

后面发现,在/etc/passwd里面,新增的用户用的Shell与root用户的不一样。

Root用的是/bin/bash

新增用户默认用的是/bin/sh

用ls -l /bin/sh发现

/bin/sh -> /bin/dash

dash与bash是不一样的,把/bin/sh改成/bin/bash后,

在我的ubuntu上运行 sudo gedit /etc/passwd 结果如下 也可以用env命令查看 shell=/bin/bash/

hailongzhou:x:1000:1000:hailongzhou,,,:/home/hailongzhou:/bin/bash
用户的shell确实是bash 可是 /bin/sh -> /bin/dash
修改Ubuntu的/bin/sh的默认连接:
终端输入:
root@zhanghc-Ubuntu:~# cd /bin
root@zhanghc-Ubuntu:/bin# ls -l /bin/sh
lrwxrwxrwx 1 root root 4 2008-04-28 19:59 /bin/sh -> dash //默认位dash
root@zhanghc-Ubuntu:/bin# ln -sf bash /bin/sh //软链接 -f表示强制
root@zhanghc-Ubuntu:/bin# ls -l /bin/sh
lrwxrwxrwx 1 root root 4 2008-05-01 22:51 /bin/sh -> bash //现在位bash了

git 后面的参数可以用Tab键补齐了
bash 与dash的区别
bash – GNU Bourne-Again SHell
dash – Debian Almquist Shell
可以分别man bash / man dash看一下。

那么怎么把sh改为指向bash呢?
最暴力的方法当然是直接把/bin/sh的软链接改到bash中,
如:ln -s /bin/bash /bin/sh
但是,有优雅一些的方法,
sudo dpkg-reconfigure dash
出现菜单问你是否要dash的时候,选no就可以了。
再次检查一下, ls /bin/sh -al 发现软链接指向/bin/bash就可以了。

awk的常见用法

2016年12月7日 评论已被关闭

awk的常见用法

http://www.cnblogs.com/coldplayerest/archive/2012/06/12/2546331.html

1. 对一列数据求和

awk ‘BEGIN {sum=0} {sum+=$1} END {print sum}’ data.txt

2. 对一列数据求和、求平均值

awk -F ‘,’ ‘BEGIN {sum=0 ;count=0} {sum +=$5; count++;} END {print “sum=”sum” count=”count ” avg=”sum/count}’

3. 成批rename文件

find * -type f | awk ‘{print “mv “$1” “$1″.new”}’
4. 当一列匹配某一字符串时打印

$ awk ‘$4 ~/Technology/’ employee.txt
200 Jason Developer Technology $5,500
300 Sanjay Sysadmin Technology $7,000
500 Randy DBA Technology $6,000
5. printf

awk ‘{ printf “%-10s %s\n”, $1, $2 }’ BBS-list

分类: Shell脚本编程 标签:

Shell脚本8种字符串截取方法总结

2016年12月4日 评论已被关闭

Shell脚本8种字符串截取方法总结
http://www.jb51.net/article/56563.htm
这篇文章主要介绍了Shell脚本8种字符串截取方法总结,每个方法给出了实例代码和操作结果,一目了然,需要的朋友可以参考下
Linux 的字符串截取很有用。有八种方法。
假设有变量 var=http://www.aaa.com/123.htm.
1. # 号截取,删除左边字符,保留右边字符。
复制代码 代码如下:

echo ${var#*//}
其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符
即删除 http://
结果是 :www.aaa.com/123.htm
2. ## 号截取,删除左边字符,保留右边字符。
复制代码 代码如下:

echo ${var##*/}
##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符
即删除 http://www.aaa.com/
结果是 123.htm
3. %号截取,删除右边字符,保留左边字符
复制代码 代码如下:

echo ${var%/*}
%/* 表示从右边开始,删除第一个 / 号及右边的字符
结果是:http://www.aaa.com
4. %% 号截取,删除右边字符,保留左边字符
复制代码 代码如下:

echo ${var%%/*}
%%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符
结果是:http:
5. 从左边第几个字符开始,及字符的个数
复制代码 代码如下:

echo ${var:0:5}
其中的 0 表示左边第一个字符开始,5 表示字符的总个数。
结果是:http:
6. 从左边第几个字符开始,一直到结束。
复制代码 代码如下:

echo ${var:7}
其中的 7 表示左边第8个字符开始,一直到结束。
结果是 :www.aaa.com/123.htm
7. 从右边第几个字符开始,及字符的个数
复制代码 代码如下:

echo ${var:0-7:3}
其中的 0-7 表示右边算起第七个字符开始,3 表示字符的个数。
结果是:123
8. 从右边第几个字符开始,一直到结束。
复制代码 代码如下:

echo ${var:0-7}
表示从右边第七个字符开始,一直到结束。
结果是:123.htm
注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示)

分类: Shell脚本编程 标签:

探讨shell命令中 >/dev/null 2>&1的实现原理

2016年11月27日 评论已被关闭

探讨shell命令中 >/dev/null 2>&1的实现原理
https://my.oschina.net/u/566345/blog/78935
首先标准输入,标准输出,标准错误:
标准输入是程序可以读取其输入的位置。缺省情况下,进程从键盘读取 stdin 。
标准输出是程序写入其输出的位置。缺省情况下,进程将 stdout 写到终端屏幕上。
标准错误是程序写入其错误消息的位置。缺省情况下,进程将 stderr 写到终端屏幕上。
为什么有这三个很重要的概念呢?我们知道,一个程序要运行,需要有输入、输出,如果出错,还要能表现出自身的错误。这是就要从某个地方读入数据、将数据输出到某个地方,出错了还要把错误给弄到一个地方去.这就够成了数据流(stream)。所以通常情况,每个 Unix 程序在启动时都会打开三个流,一个用于输入,一个用于输出,一个用于打印诊断或错误消息。

有了这三个概念.

再说说重定向:

数据流重导向(重定向)就是将某个指令(命令)执行后的执行返回值,一般这些返回值就是你执行完后出现在屏幕上那些结果数据,如果我不想让他默认流向屏幕.那么我可以把这些结果数据传输到其他的地方,例如文件或者装置(例如打印机,不过在Linux里面一切都一切都是文件,所以打印机这样的设备也是文件咯).这样数据就跑被我导向其他地方了.你懂的.所以东西都输出到屏幕,如果数据太多太乱.我们也受不了啊.而且屏幕的terminal一关.东西就再也找不到了.如果我重定向到一个文件.这样就可以长期保存执行的日志了.

>数据流重导向:输出导向,会替换被导向的文件内容.
>>数据流重导向:输出导向,不会替换被导向的文件内容.会在屁股后面累加数据.
继续看看文件描述符:

维基百科,自由的百科全书上面是这样说的,文件描述符(File descriptor)是计算机科学中的一个术语,是一个用于表述指向文件的引用的抽象化概念。文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。文件描述符的优点主要有两个:基于文件描述符的I/O操作兼容POSIX标准。在UNIX、Linux的系统调用中,大量的系统调用都是依赖于文件描述符。看来这东西还真的有点抽象.也就是说如果程序不打开,文件孤单的在磁盘上面的时候是没有文件描述符的.可以想象一下.第一个打开的文件是0,第二个是1,依此类推。Unix 操作系统通常给每个进程能打开的文件数量强加一个限制。更甚的是,unix 通常有一个系统级的限制。当然真是的情况是0,1,2一般已经被某些概念占用.再加上系统启动后已经不知道打开了多少文件.所以.我们自己一般打开文件的时候描述符估计也已经到很大的数据了.但是这文件描述符缺点也是有的.比如完成的代码可读性也就会变得很差.你想啊.0,1,2….22231是知道是啥玩意儿?还好POSIX 定义了 STDIN_FILENO、STDOUT_FILENO 和 STDERR_FILENO 来代替 0、1、2。这三个符号常量的定义位于头文件 unistd.h。文件描述符的有效范围是 0 到 OPEN_MAX。一般来说,每个进程最多可以打开 64 个文件(0 — 63)。对于 FreeBSD 5.2.1、Mac OS X 10.3 和 Solaris 9 来说,每个进程最多可以打开文件的多少取决于系统内存的大小,int 的大小,以及系统管理员设定的限制。Linux 2.4.22 强制规定最多不能超过 1,048,576 。

综合上面的基本概念:下面的也就不难理解了.

标准输入 (stdin) :文件描述符为 0 ,使用 < 或 << ;(你不会非要写成0<或0<<吧.其实这个也没错.不过太累人了)其实可以理解为这个箭头指向哪里数据就往哪里跑.这里是输入(stdin).命令就通过<来获取数据.等于数据是从左边往命令里面流.

标准输出 (stdout):文件描述符为 1 ,使用 > 或 >> ;(你不会非要写成1>或1>>吧.其实这个也没错.不过太累人了)输出的时候当如不能用<或者<<,因为命令总是在前面嘛.这里命令要输出数据.所以数据的来源是命令,数据就会随着箭头指向你给的方向.

标准错误输出(stderr):文件描述符为 2 ,使用 2> 或 2>>;

再举例说明:

首先command >file 2>file 的意思是将命令所产生的标准输出信息,和错误的输出信息送到file中.command >file 2>file 这样的写法,stdout和stderr都直接送到file中, file会被打开两次,这样stdout和stderr会互相覆盖,这样写相当使用了两个同时去抢占file的管道.定向了2次.

那如果使用command >file 2>&1 这条命令就将stdout直接送向file, stderr 继承了第一次重定向(FD1)到管道后,再被送往file,此时,file 只被打开了一次,也只使用了一个管道FD1,它包括了stdout和stderr的内容.还可以这样理解.想是把file用管道接通了标准输出.然后把2代表的标准错误输出接到1代表的标准信息输出上面.就都通向了file了.

从IO效率上,前一条命令的效率要比后面一条的命令效率要低,所以在编写shell脚本的时候,较多的时候我们会用command > file 2>&1 这样的写法.

在看看一个实例(加深相关的理解,此实例引用网上博客.说是intel的笔试题):

问题:下面程序的输出是什么?(intel笔试2011)

int main(){
fprintf(stdout,”Hello “);
fprintf(stderr,”World!”);
return0;
}
然后发现输出是
World!Hello
而不是:
Hello World!

这是为什么呢?在默认情况下,stdout是行缓冲的,他的输出会放在一个buffer里面,只有到换行的时候,才会输出到屏幕。而stderr是无缓冲的,会直接输出,举例来说就是printf(stdout, “xxxx”) 和 printf(stdout, “xxxx\n”),前者会憋住,直到遇到新行才会一起输出。而printf(stderr, “xxxxx”),不管有么有\n,都输出.

最后:

看看什么叫/dev/null

UFO@UFO~:cd /dev
UFO@UFO :/dev$ls -l null
crw-rw-rw- 1 root root 1, 3 Feb 14 2012 null
看到了吧?是个字符设备文件(c).而这个东西呢?你可以叫他”黑洞”, Blackhole?NO.不是天文学里面的黑洞.它非常等价于一个只写文件. 所有写入它的内容都会永远丢失. 而尝试从它那儿读取内容则什么也读不到. 然而, /dev/null 对命令行和脚本都非常的有用.
再来看看在glibc库的stdio.h头文件中:

#define stdin (&__sF[0])
#define stdout (&__sF[1])
#define stderr (&__sF[2])
比如

fprintf(stderr, “UFO\n”);//那么将把”UFO”作为标准错误输出
在shell命令中,0,1和2分别对应glibc中的stdin,stdout和stderr,上面我们已经大概了解到了:

0 对应stdin 即标准输入
1 对应stdout 即标准输出
2 对应stderr 即标准错误输出
所以>/dev/null表示将程序通过printf或者fprintf打印到handle为1的stdout文件的信息,送到/dev/null空洞文件,/dev/null节点对应的kernel实现就是直接返回写入的字节数,所以程序认为成功存储到/dev/null了,但是>/dev/null这个操作不能将fprintf(stderr, “UFO\n”)打印到stderr上的字符串送到>/dev/null下,所以必须使用2>&1命令,表示shell将送到2 stderr中的数据转送到1 stdout中,所以这样stderr中会显示到terminal上的信息也将被转送到/dev/null下了.

又看个实例吧:

luther@gliethttp:~$ cat a.c
#include <stdio.h>
int main(int argc, char *argv[])
{
fprintf(stdout,”luther stdout\n”);
fprintf(stderr,”luther stderr\n”);
return 0;
}
luther@gliethttp:~$ gcc a.c
luther@gliethttp:~$ ./a.out
luther stdout
luther stderr
luther@gliethttp:~$ ./a.out >/dev/null
luther stderr//可以看到>/dev/null操作并不会将stderr信息送到/dev/null下
写一个test.sh脚本

luther@gliethttp:~$ chmod +x test.sh
luther@gliethttp:~$ cat test.sh
exec ./a.out >/dev/null
luther@gliethttp:~$ ./test.sh
luther stderr //可以看到shell也不会将stderr信息送到/dev/null下
luther@gliethttp:~$ cat test.sh
exec ./a.out >/dev/null 2>&1
luther@gliethttp:~$ ./test.sh
luther@gliethttp:~$ //什么也没有输出,stderr信息被2>&1命令成功变为stdout信息,进而送入了/dev/null淹没
luther@gliethttp:~$ cat test.sh
exec ./a.out >/dev/null 1>&2
./test.sh
luther stdout
luther stderr
luther@gliethttp:~$
当然对于tee操作也同样存在如上问题,如果打印到stderr的log将不能被tee操作捕获,所以可以将stderr重定向到stdout来解决这个问题,

继续看看实例:

luther@gliethttp:~$ ./a.out
luther stdout
luther stderr
luther@gliethttp:~$ ./a.out|tee luther.txt
luther stdout
luther stderr
luther@gliethttp:~$ cat luther.txt
luther stdout
luther@gliethttp:~$ ./a.out 2>&1|tee luther.txt
luther stderr
luther stdout
luther@gliethttp:~$ cat luther.txt
luther stderr
luther stdout
luther@gliethttp:~$ ./a.out 1>&2|tee luther.txt
luther stderr
luther stdout
luther@gliethttp:~$ cat luther.txt
luther@gliethttp:~$ //啥东西都没有,因为stdout被定向到stderr,所以所有log信息都不能被tee捕获
对于1>&2因为作为一个命令将被shell解析,所以放在哪里都可以,1>&2将影响到该组命令中所有的log输出,比如:
luther@gliethttp:~$ 1>&2 ./a.out|tee luther.txt
luther stderr
luther stdout
luther@gliethttp:~$ ./a.out 1>2 //只输出stderr
luther stderr
luther@gliethttp:~$ ./a.out 2>1 //只输出stdout
luther stdout
OK.不想写了.忙的很.上面的文章我只是添油加醋的把网络上很多因为大抄而散落各地的文章乱七八糟的整合了一下.所以我是站在巨人的肩上来了一次大抄.感谢那些巨人吧.其实上面提到的概念估计就这篇整合文章也不能完全解释的非常彻底.相关的概念更多的还在于实践和看文档再加自己的大脑过滤与思考.希望和大家探讨!

分类: Shell脚本编程 标签:

Shell: /dev/null 2>&1详解

2016年11月27日 评论已被关闭

Shell: /dev/null 2>&1详解
http://justcoding.iteye.com/blog/1944237
博客分类: Ubuntu / Mac / Github / Aptana / Nginx / Shell / Linux

1,可以将/dev/null看作”黑洞”. 它非常等价于一个只写文件. 所有写入它的内容都会永远丢失. 而尝试从它那儿读取内容则什么也读不到. 然而, /dev/null对命令行和脚本都非常的有用.
用处:
禁止标准输出. 1 cat $filename >/dev/null # 文件内容丢失,而不会输出到标准输出.
禁止标准错误. 2>/dev/null 这样错误信息[标准错误]就被丢到太平洋去了.

2, 1>/dev/null 2>&1的含义

> 代表重定向到哪里,例如:echo “123” > /home/123.txt
1 表示stdout标准输出,系统默认值是1,所以”>/dev/null”等同于”1>/dev/null”
2 表示stderr标准错误
& 表示等同于的意思,2>&1,表示2的输出重定向等同于1

那么本文标题的语句:
1>/dev/null 首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。
2>&1 接着,标准错误输出重定向等同于 标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。

3,/dev/zero文件代表一个永远输出 0的设备文件,使用它作输入可以得到全为空的文件。因此可用来创建新文件和以覆盖的方式清除旧文件。

下面使用dd命令将从zero设备中创建一个10K大小(bs决定每次读写1024字节,count定义读写次数为10次),但内容全为0的文件。
dd if=/dev/zero of=file count=10 bs=1024

shell中可能经常能看到:>/dev/null 2>&1

命令的结果可以通过%>的形式来定义输出

分解这个组合:“>/dev/null 2>&1” 为五部分。

1:> 代表重定向到哪里,例如:echo “123” > /home/123.txt
2:/dev/null 代表空设备文件
3:2> 表示stderr标准错误
4:& 表示等同于的意思,2>&1,表示2的输出重定向等同于1
5:1 表示stdout标准输出,系统默认值是1,所以”>/dev/null”等同于 “1>/dev/null”

因此,>/dev/null 2>&1 也可以写成“1> /dev/null 2> &1”

那么本文标题的语句执行过程为:
1>/dev/null :首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。
2>&1 :接着,标准错误输出重定向 到 标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。

最常用的方式有:

command > file 2>file 与command > file 2>&1

它们有什么不同的地方吗?
首先command > file 2>file 的意思是将命令所产生的标准输出信息,和错误的输出信息送到file 中.command > file 2>file 这样的写法,stdout和stderr都直接送到file中, file会被打开两次,这样stdout和stderr会互相覆盖,这样写相当使用了FD1和FD2两个同时去抢占file 的管道。
而command >file 2>&1 这条命令就将stdout直接送向file, stderr 继承了FD1管道后,再被送往file,此时,file 只被打开了一次,也只使用了一个管道FD1,它包括了stdout和stderr的内容。
从IO效率上,前一条命令的效率要比后面一条的命令效率要低,所以在编写shell脚本的时候,较多的时候我们会command > file 2>&1 这样的写法。

分类: Shell脚本编程 标签:

Linux-shell给变量设置默认值

2016年11月27日 评论已被关闭

Linux-shell给变量设置默认值
http://blog.sina.com.cn/s/blog_8a18c33d01019msl.html
通常shell中我们需要给变量设置默认值,可能会写出如下代码
Shell代码
#!/bin/bash
if [ ! $1 ]; then
$1=’default’
fi
显然这种方式在变量少的时候没啥问题,一旦变量多起来,我们可能就有大量的重复劳动(if判断)
有没有比较优雅的方式,不用写一大堆if判断,显然答案是有的
1.变量为null时
Shell代码
#当变量a为null时则var=b
var=${a-b}
2.变量为null且为空字符串的时候
Shell代码
#当变量a为null或为空字符串时则var=b
var=${a:-b}

分类: Shell脚本编程 标签:

shell脚本报错:”[: =: unary operator expected”

2016年11月2日 评论已被关闭

shell脚本报错:”[: =: unary operator expected”
http://blog.csdn.net/goodlixueyong/article/details/6564591
shell脚本报错:”[: =: unary operator expected”

在匹配字符串相等时,我用了类似这样的语句:

if [ $STATUS == “OK” ]; then

echo “OK”

fi

在运行时出现了 [: =: unary operator expected 的错误,就一直找不到原因,尝试了删除等号两侧的空格和括号里的空格都不管用,最后baidu了一下,才找到原因。把语句改成这样就不会出错了.

if [[ $STATUS = “OK” ]];

then

echo “OK”

fi

究其原因,是因为如果变量STATUS值为空,那么就成了 [ = “OK”] ,显然 [ 和 “OK” 不相等并且缺少了 [ 符号,所以报了这样的错误。当然不总是出错,如果变量STATUS值不为空,程序就正常了,所以这样的错误还是很隐蔽的。

或者用下面的方法也能避免这种错 误:if [ “$STATUS”x == “OK”x ]; then echo

“OK”fi。当然,x也可以是其他字符。顺便提一点,shell中有没有双引号在很多情况下是一致的。

转自:http://hi.baidu.com/vishare/blog/item/bd8ab9ee289753252cf53417.html

分类: Shell脚本编程 标签:

shell脚本实现的网站日志分析统计(可以统计9种数据)

2016年6月6日 评论已被关闭

shell脚本实现的网站日志分析统计(可以统计9种数据)
http://www.jb51.net/article/50444.htm
这篇文章主要介绍了shell脚本实现的网站日志分析统计,可以统计9种数据,如访问量、带宽、访客量、IP统计、搜索引擎等,需要的朋友可以参考下

写了个shell脚本,可以用来统计每天的访问日志,并发送到电子邮箱,方便每天了解网站情况。
脚本统计了:
1、总访问量
2、总带宽
3、独立访客量
4、访问IP统计
5、访问url统计
6、来源统计
7、404统计
8、搜索引擎访问统计(谷歌,百度)
9、搜索引擎来源统计(谷歌,百度)
复制代码 代码如下:

#!/bin/bash
log_path=/home/www.jb51.net/log/access.log.1
domain=”jb51.net”
email=”log@jb51.net”
maketime=`date +%Y-%m-%d” “%H”:”%M`
logdate=`date -d “yesterday” +%Y-%m-%d`
total_visit=`wc -l ${log_path} | awk ‘{print $1}’`
total_bandwidth=`awk -v total=0 ‘{total+=$10}END{print total/1024/1024}’ ${log_path}`
total_unique=`awk ‘{ip[$1]++}END{print asort(ip)}’ ${log_path}`
ip_pv=`awk ‘{ip[$1]++}END{for (k in ip){print ip[k],k}}’ ${log_path} | sort -rn | head -20`
url_num=`awk ‘{url[$7]++}END{for (k in url){print url[k],k}}’ ${log_path} | sort -rn | head -20`
referer=`awk -v domain=$domain ‘$11 !~ /http:\/\/[^/]*'”$domain”‘/{url[$11]++}END{for (k in url){print url[k],k}}’ ${log_path} | sort -rn | head -20`
notfound=`awk ‘$9 == 404 {url[$7]++}END{for (k in url){print url[k],k}}’ ${log_path} | sort -rn | head -20`
spider=`awk -F'”‘ ‘$6 ~ /Baiduspider/ {spider[“baiduspider”]++} $6 ~ /Googlebot/ {spider[“googlebot”]++}END{for (k in spider){print k,spider[k]}}’  ${log_path}`
search=`awk -F'”‘ ‘$4 ~ /http:\/\/www\.baidu\.com/ {search[“baidu_search”]++} $4 ~ /http:\/\/www\.google\.com/ {search[“google_search”]++}END{for (k in search){print k,search[k]}}’ ${log_path}`
echo -e “概况\n报告生成时间:${maketime}\n总访问量:${total_visit}\n总带宽:${total_bandwidth}M\n独立访客:${total_unique}\n\n访问IP统计\n${ip_pv}\n\n访问url统计\n${url_num}\n\n来源页面统计\n${referer}\n\n404统计\n${notfound}\n\n蜘蛛统计\n${spider}\n\n搜索引擎来源统计\n${search}” | mail -s “$domain $logdate log statistics” ${email}
需要修改的三个变量log_path,domain和email,然后把此脚本添加到计划任务,就可以每天接收到统计的数据了。

分类: Shell脚本编程 标签:

tar打包整个目录(可排除子目录)几种方法

2016年6月6日 评论已被关闭

tar打包整个目录(可排除子目录)几种方法
http://www.111cn.net/sys/linux/54524.htm
tar命令是linux系统中一个常用的文件压缩与解压的命令了,我们通称为打包了,下面我们一起来看看linux tar打包目录与有条件打包目录命令。
例1。压缩并打包目录

tar -czf small.tar.gz small(目录名)  ;
例2。

tar zcvf backup.tar.gz site/* –exclude=site/attach –exclude=site/images
简单解释一下:
ls -l | grep “^-” 用来把当前目录下所有文件列出来,不包括子目录;
awk ‘{print “dollar”8}’ 用来把ls和grep输出的文件名取出来;
xargs 将前面一串的输出,也就是一个文件名的列表组织成一个参数传递给tar命令。
如果只是排除一两个目录,可以用tar命令的–exclude= 选项。
例如排除site目录下的attach和images目录:
tar zcvf backup.tar.gz site/* –exclude=site/attach –exclude=site/images

例2
tar 打包目录时排除其中某一子目录的方法

具体的命令如下:

tar cfz ff-bb.cn.tar.gz /var/www/ff-bb.cn/ –exclude=var/www/ff-bb.cn/download
如果需要排除多个子目录,那么就执行

tar –exclude=var/www/ff-bb.cn/download –exclude=var/www/ff-bb.cn/download2 cfz hosteguide.com.tar.gz /var/www/hosteguide.com/
注意 –exclude后面的排除目录后不能带/ ,否则不起作用。
解包到指定的目录:使用 tar 的 -C 选项,如 tar xvf newarc.tar.gz -C tmp/a/b/c。

如:
tar –exclude=/usr/local/nginx/html/htdocs/download/backup  –exclude=/usr/local/nginx/html/htdocs/othersites -czvf /usr/local/resourcebackup/resource-`date +”%Y-%m-%d_%H-%M-%S”`.tar.gz /usr/local/nginx/html/htdocs/*

例3
假设 test目录下有 1 2 3 4 5 这5个目录
现在要将 3 4 5目录tar打包,1和2目录不要
命令如下

tar -zcvf  test.tar.gz –exclude=1 –exclude=2 test

tar -zcvf  test.tar.gz –exclude=test/1 –exclude=test/2 test
看man tar帮助,–exclude后面跟的好像是正则
注意: 要打包的test必须在命令最后,不然没有效果.刚才郁闷了半天

分类: Shell脚本编程 标签:

tar排除指定目录打包

2016年6月6日 评论已被关闭

tar排除指定目录打包

http://hxl2009.blog.51cto.com/779549/476513
假设 test目录下有 1 2 3 4 5 这5个目录
现在要将 3 4 5目录tar打包,1和2目录不要
命令如下:
tar -zcvf test.tar.gz –exclude=1 –exclude=2 test

tar -zcvf test.tar.gz –exclude=test/1 –exclude=test/2 test
看man tar帮助,–exclude后面跟的好像是正则
注意: 要打包的test必须在命令最后,不然没有效果.

将 /etc/ 内的所有文件备份下来,并且保存其权限!
tar -zxvpf /tmp/etc.tar.gz /etc
#这个 -p 的属性是很重要的,尤其是当您要保留原本文件的属性时!
在 /home 当中,比 2010/06/01 新的文件才备份
tar -N ‘2010/06/01’ -zcvf home.tar.gz /home
备份 /home, /etc ,但不要 /home/dmtsai
tar –exclude /home/dmtsai -zcvf myfile.tar.gz /home/* /etc
本文出自 “技术成就梦想” 博客,请务必保留此出处http://hxl2009.blog.51cto.com/779549/476513

分类: Shell脚本编程 标签:

Shell脚本中的:>/dev/null 2>&1 的作用

2016年6月6日 评论已被关闭

Shell脚本中的:>/dev/null 2>&1 的作用
http://blog.csdn.net/yasi_xi/article/details/8637069
转自:http://wangqiaowqo.iteye.com/blog/1354226

shell中可能经常能看到:>/dev/null 2>&1

命令的结果可以通过%>的形式来定义输出

/dev/null 代表空设备文件
> 代表重定向到哪里,例如:echo “123” > /home/123.txt
1 表示stdout标准输出,系统默认值是1,所以”>/dev/null”等同于”1>/dev/null”
2 表示stderr标准错误
& 表示等同于的意思,2>&1,表示2的输出重定向等同于1

那么本文标题的语句:
1>/dev/null 首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。
2>&1 接着,标准错误输出重定向等同于 标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。
A. 1> /dev/null 表示将命令的标准输出重定向到 /dev/null2>/dev/null 表示将命令的错误输出重定向到 /dev/null1 – denotes stdout ( standard output )2 – denotes stderr  ( standard error )/dev/null就相当与windows里的回收站,只是进去了不能再出来了。>/dev/null 就是将标准输出和标准出错的信息屏蔽不显示
B.>/dev/null 2>&1   also can write  as  1>/dev/null 2>&1     – stdout redirect to /dev/null (no stdout) ,and redirect stderr to stdout  (stderr gone as well) . end up it turns both stderr and stdout off
C.a little practice may help to undstand above .  #ls /usr  /nothing #ls /usr  /nothing  2>/dev/null #ls /usr  /nothing  >/dev/null 2>&1

我们经常会在UNIX系统下的一些脚本中看到类似”2>&1″这样的用法,例如“/path/to/prog 2>&1 > /dev/null &”,那么它的具体含义是什么呢?
UNIX有几种输入输出流,它们分别与几个数字有如下的对应关系:0-标准输入流(stdin),1-标准输出流(stdout),2-标准错误流 (stderr)。”2>&1″的意思就是将stderr重定向至stdout,并一起在屏幕上显示出来。如果不加数字,那么默认的重定向动作是针对stdout(1)的,比如”ls -l > result”就等价于”ls -l 1 > result”。这样便于我们更普遍性的理解重定向过程。
下面举例说明:
#cat std.sh
#!/bin/sh
echo “stdout”
echo “stderr” >&2

#/bin/sh std.sh 2>&1 > /dev/null
stderr

#/bin/sh std.sh > /dev/null 2>&1

第一条命令的输出结果是stderr,因为stdout和stderr合并后一同重定向到/dev/null,但stderr并未被清除,因此仍将在屏幕中显示出来;第二条命令无输出,因为当stdout重定向至/dev/null后,stderr又重定向到了stdout,这样stderr也被输出到了/dev/null。

今天在做例行工作的时候,发现机器上的sendmail进程奇多无比,并且机器IO好像也很慢。后来发现在/var/spool/clientmqueue目录下ls几乎要死人 – 最少有10万个文件

ps|grep sendmail看这些sendmail进程里面都有/var/spool/clientmqueue

cd过去随便打开了个文件看了下,发现是我crontab里面执行的程序的exception,估计是我的crontab每次执行,linux都试图发邮件给crontab的用户但是又没有配sendmail,所以东西就都被扔到/var/spool/clientmqueue下面了。然后我才明白为啥以前别人写的crontab要加上> /dev/null 2>&1,原来这样就不会每次执行crontab都把结果或者excetion发邮件了。

把这10万个文件删掉后,一切恢复正常

问题现象:
linux操作系统中的/var/spool/clientmqueue/目录下存在大量文件。
原因分析:系统中有用户开启了cron,而cron中执行的程序有输出内容,输出内容会以邮件形式发给cron的用户,而sendmail没有启动所以就产生了这些文件;
解决办法: 1、 将crontab里面的命令后面加上> /dev/null 2>&1
2、知识点:
2>:重定向错误。
2>&1:把错误重定向到输出要送到的地方。即把上述命令的执行结果重定向到/dev/null,即抛弃,同时,把产生的错误也抛弃。
3、具体代码:
(1)、# crontab -u cvsroot -l
01 01 * * * /opt/bak/backup
01 02 * * * /opt/bak/backup2
(2)、# vi /opt/bak/backup
#!/bin/sh
cd /
getfacl -R repository > /opt/bak/backup.acl
(3)、# vi /opt/bak/backup2
#!/bin/sh
week=`date +%w`
tar zcvfp /opt/bak/cvs$week/cvs.tar.gz /repository >/dev/null 2>&1
4、清除/var/spool/clientmqueue/目录下的文件:
# cd /var/spool/clientmqueue
# rm -rf *
如果文件太多,占用空间太大,用上面命令删除慢的话,就执行下面的命令:
# cd /var/spool/clientmqueue
# ls | xargs rm -f
在一個風和日麗的夜晚,我坐在家裡看著電視,後來手機一陣響起,結果是楊老師發現一台主機發生異常,伺服器的 /var/spool/mqueue 目錄被塞了一堆還沒有寄出的信件,而當時沒有把 /var/spool 另外分割出來,所以也影響到了系統 root (/) 區塊,只剩六百多 MB 可以使用,這時一想會有幾個可能.

這台 server 有幫學校的 PC 做寄送信件,所以可能是廣告信在寄出.

使用這台 server 做 mail 寄信的機器,可能是中毒,於是就不斷的送信出去.
一開始只有想到這兩個原因,但是可要把被吞掉的空間給吐出來,所以就打算把所有的 mail queue 都先砍了,當然,要先停掉 mail service.
在砍這些正在排隊的信件時,發現一件事,就是裡面的檔案太多了,使用 ls 命令就變得超級遲頓,沒有反應,使用 mailq 來看看到底是那些信被 queue 住也沒辦法,後來想想算了,只好全剖砍了,不要再玩下去,之後,很順手的下了 rm -rf * 這下子呢,發生了一件很離奇的事,居然檔案太多無法刪除,第一次聽到 rm 在 complain (我是聽到的,楊老師是實作者,所以他有看到 ^^).
那個 error 是: bash: /bin/rm: Argument list too long
雖然無法刪除,但是楊兄並不放棄,到主機面前,開啟了 X Window 之後使用那 Linuxer 最常使用的鸚鵡螺 (nautilus) 開啟到 /var/spool/mqueue. 喔 ~ 可以使用 X Window 來刪呢 ! 後來想說即然 X Window 有這麼大的本事,那麼就用它來刪了其它的 queue files 就好啦,於是掛上電話,放楊兄一個人努力的在機房刪著 …
當然我也沒有閒著,電視劇剛好演完,於是開啟我的工作伙伴,再度當網路潛水艇 … 游著游著,突然想到,何不使用 find 來刪除看看 ? 於是刪回歷史文件,發現一個命令就是 find ./ | xargs rm -rf 千萬別小看這小小的指令,因為在我看完之後不久,楊兄打進來,說已經刪到手軟,這時也是晚上十點了,於是我就推薦了這個這道指令,嗯,很好,全都刪了,還頗快的 …
喔,還沒說為什麼會刪到手軟,是因為 nautilus 在 Load 目錄時,是分批的,不是一次全部讀,所以一次大約是幾千封在讀,刪了之後,沒想到又冒出了還有幾千封 … 真是嚇死人,後來推論應該是分批的關係.
在下了 find ./ | xargs rm -rf 之後,還在訝異快速之餘,就發現時間不多了,學校也要關門,所以就先 say bye bye,在現場苦命的楊兄也回家休息了.
分析:
rm 有最大一次刪除的數量,所以當一個目錄裡有太多的檔案或目錄時,就會出現錯誤,小弟試過應該是在二萬以下,而使用 find ./ | xargs rm -rf 的目的是先使用 find 列出檔案,再導向到 xargs,xargs 再喂給 rm,在這裡,xargs 會分批依照 rm 的最大數量餵給 rm,然後就可以順利刪除檔案了
。而真正的原因,有可能是 rm 的版本或是檔案系統的問題,我也不再繼續追就,反正能辦好事就好
下面提供當時小弟測試的一個小小 shell script
下載:
mk-file.sh
(這個 shell script 會有目錄下產生 20000 個檔案。)
接下來來做個小小測試:
root # mkfile.sh
root #
會產生 20000 個小檔案,名稱為 test-file-{1~19999}
直接使用 rm 去刪除:
root # rm -rf test-file-*
-bash: /bin/rm: Argument list too long (會回應引數過長的訊息)
改搭配 find 來刪除
root # find ./ -iname ‘test-file-*’ | xargs rm -rf
root # ls
mk-file.sh
root #
這樣就順利被刪除了。

———————————
#tool_action
45 4 * * * /bin/sh /data/stat/crontab/exec_tool_action_analysis_db.sh >> /data/stat/logs/exec_tool_action_analysis_db.sh.log > /dev/null 2>&1

45 5 * * * /bin/sh /data/stat/crontab/exec_tool_action_analysis_user.sh >> /data/stat/logs/exec_tool_action_analysis_user.sh.log > /dev/null 2>&1

否则在/var/spool/clientmqueue 下会产生以下文件:
-rw-rw—- 1 smmsp   smmsp  975 Jan 17 10:50 qfq0H2o4ei031197

分类: Shell脚本编程 标签:

shell中“>/dev/null 2>&1”详解

2016年6月6日 评论已被关闭

shell中“>/dev/null 2>&1”详解

shell中可能经常能看到:>/dev/null  2>&1
命令的结果可以通过 %> 的形式来定义输出,其中 %> 代表文件描述符
我们将这个命令组合:“>/dev/null 2>&1”  拆为四部分来分析下:
1:> 代表重定向到哪里,例如:echo “123” > /home/123.txt
2:首先 0> 表示stdin标准输入; 1> 表示stdout标准输出; 2> 表示stderr错误输出;
3:/dev/null 代表空设备文件
4:& 可以理解为是”等同于”的意思,2>&1,即表示2的输出重定向等同于1
5:1 表示stdout标准输出,系统默认值是1,所以”>/dev/null”等同于 “1>/dev/null”
因此,>/dev/null 2>&1 也可以写成“1> /dev/null 2> &1”
那么本文标题的语句执行过程为:
1>/dev/null :首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。
2>&1 :接着,将标准错误输出重定向 到 标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。

分类: Shell脚本编程 标签:

Linux Shell脚本的参数

2016年5月29日 评论已被关闭

Linux Shell脚本的参数
http://www.2cto.com/os/201109/103533.html
$0 —- 当前程序的名称,实际上是一个内部参数,不同于$1,$2….因为它必须有!
$# —- 传递给程序的总的参数数目,也就是那个传说中的数组大小
$? —- 上一个代码或者shell程序在shell中退出的情况,如果正常退出则返回0,反之为非0值。
$* —- 传递给程序的所有参数组成的字符串。
$@ —- 以”参数1″ “参数2” … 形式保存所有参数
$$ —- 本程序的(进程ID号)PID
$! —- 上一个命令的PID
作者“道可道非常道”

分类: Shell脚本编程 标签:

Linux BASH Shell脚本编程超级工具介绍

2016年5月21日 评论已被关闭

Linux BASH Shell脚本编程超级工具介绍
http://os.51cto.com/art/201006/207358.htm
DEC公司推出的 PDP-11 ,体积小(被称为 mini)而且价格低(10000$),在大学中引起了巨大的反响。为了方便移植,1969 年,Ken Thompson 开始写后来成为 Unix(与MULTICS相对)的第一行代码。
AD:51CTO网+ 首届中国APP创新评选大赛>>
超级工具

terminals,xterms 和 shells shell是一个全功能的编程环境。其背景知识如下。

DEC公司推出的 PDP-11 ,体积小(被称为 mini)而且价格低(10000$),在大学中引起了巨大的反响。为了方便移植,1969 年,Ken Thompson 开始写后来成为 Unix(与MULTICS相对)的第一行代码。后来, Dennis Ritchie为这个新的操作系统设计了一种新的编程语言–
C 语言。虽然 Unix 的效率不及原来的操作系统,但有三个突出的优点:
1. 可以任意移植到其他机器
2. 其中的 C 语言大大简化了编程
3. free。

终端(terminals)
Unix是可以在许多种机器上运行的操作系统,但人们又如何使用这些机器呢?他们是通过哑终端来连接到这些机器,也就是用键盘、显示器及足够的 electronics(电子元件)组成的机器与中央计算机(central computer)相连。在这些终端上,用户可以敲字符(teletypy),
这就是字符串’tty’表示终端设备文件,和’getty’命令的名称来历。为了避免键盘布局的混乱,人们创建了一个含有所有不同终端特性的(capability)文件,这就是’termcap’,参见’/etc/termcap’。linux 终端大多数用’vt100’或’linux’作为终端类型。

xterms在八十年代初期,产生了X Window System 。九十年代早期,产生了XFree86 。X Window 中一个很大的好处是可以运行多个虚拟(virtual)终端。甚至在 X Window 下就有这么个应用程序–‘xterm’。您将发现’xterm’和’virtual terminal’在很多情况下都是一样的。其他的终端模拟器(terminal emulator),如 rxvt、konsole、aterm、eterm、wterm 等等。终端模拟器(又称为虚拟终端)通过伪(pseudo) tty 设备– pty 与系统相连,并且使用自己的显示标准–xterm 。这导致不同的终端模拟器可能在一些按键或程序上存在细小的差别,取决于模拟器多大程度上遵守了’xterm’的显示标准。

shells shell是用户和linux(或者更准确的说,是你和Linux内核)之间的接口程序。 你在提示符下输入的每个命令都由shell先解释然后传给linux内核。为了在终端中运行程序,需要 shell 。shell 是操作系统的一部分,用来与用户打交道,并且可以用来协调各个命令。第一个真正的 Unix shell — ‘sh’,亦称为’Bourne shell’,诞生于 1975 年, 作者是Steve Bourne 。很快,出现了其他 shell ,如基于原始’Bourne shell’的’ksh’、’zsh’,后者常用作专属 Unixes 系统中的标准 shell ;也有一些从 C 语言中衍生出来的 shell , 如’csh’或’tcsh’。在 linux 中,标注的 shell 是’bash’,即 the GNU Bourne-Again Shell 。这个 shell功能非常强大,压缩的 man page 就有 50 KB 。

Shell 起步
首先,有一点小说明:在平常应用中,建议您不要用’root’帐号运行 shell , 如果您还是新手,这一点尤其要注意。作为普通用户,不管您有意还是无意,都无法破坏系统;但如果是’root’,那就不同了,只要敲几个字母,就可能导致灾难性后果。
当您登入系统或打开一个 xterm 窗口,首先看到的是提示符(prompt)。Red Hat linux的标准提示符包括了您的用户名、登入的主机名(没有设置的话,是’localhost’)、 当前所在的目录(working directory)、提示符号:
[tom@belbo tom]$
我以用户名’tom’登入名为’belbo’的主机,当前在我的 home 目录–‘/home/tom’中。
‘root’的提示符:
[root@belbo root]#
除了不同的用户名外,提示符号由’$’变成了’#’。根据 Bourne shell 的传统,普通用户的提示符以’$’结尾,而超级用户用’#’。提示符的每个部分都可以定制,您在后面将有更深的了解。
要运行命令的话,您只要在提示符后敲进命令,然后在按 键。shell将在其路径中(详情见后)搜索这个命令,找到以后就运行,并在终端里输出相应的结果(如果有的话),命令结束后,再给出新的提示符:
[tom@belbo tom]$ whoami
tom
[tom@belbo tom]$
当您敲 ENTER 时,光标(cursor)在哪里并不要紧,因为 shell 总是会整行地读取。

基本的命令有:’ls’(list directory ,列出目录内容)、’cp’(copy ,复制)、’mv’(move / rename ,移动/重命名),’cd ‘(change directory ,改变目录),这些命令后面都可以跟上一帮可选项,这方面 man page 有详细的介绍(man ls, man mv 等等)。
下面简单介绍一下几个术语(terminology)。
命令可能带一些可选项(options)、参数(arguments):mv -i file dir
其中’-i’是命令’mv’的一个可选项,而’file’和’dir’则是参数。 所有可选项在该命令的man page 都中有详细的介绍(此例中用 man mv),而参数则由您提供。可选项决定命令如何工作,而参数则用于确定命令作用的目标。

分类: Shell脚本编程 标签: ,

shell 脚本调试方法

2016年5月13日 评论已被关闭

shell 脚本调试方法
http://blog.csdn.net/gsnumen/article/details/8004644
shell 脚本调试方法

如果自己写的shell脚本运行崩溃时, 有种方法能提示在 什么时候 哪个文件 的 哪个函数 哪行语句 出现了问题, 是不是会帮助自己更快解决问题呢?
以下就是介绍这种方法:

1 将 mylog 放在 /etc 下
[cpp] view plain copy
#!/bin/bash
# ########################################################
# Filename: mylog
# Description: debug shell script
# Example:
#
# #!/bin/bash
# #file: xxx.sh
# source /etc/mylog log debug error info notice warn echo
# mylog_error “gaga gaga gagaga\n”;
#
##############################################

# Aliases are not expanded when the shell is not interactive, unless the
#+ expand_aliases shell option is set using shopt
shopt -s expand_aliases

OK=”\033[32m OK \033[0m”;
ERROR=”\033[31m ERROR \033[0m”;
FALSE=”\033[31m FALSE \033[0m”;
SUCCESS=”[SUCCESS]”;

alias mylog=’#’;
alias mylog_debug=’#’;
alias mylog_error=’#’;
alias mylog_echo=’#’;
alias mylog_info=’#’;
alias mylog_notice=’#’;
alias mylog_warn=’#’;
alias mylog_error=’#’;

for i in $@
do
case “$i” in
“log”)
alias mylog=’echo -ne $(/bin/date +%Y-%m-%d) $(/bin/date +%H:%M:%S) $(basename $0) $FUNCNAME $LINENO ‘;
;;
“info”)
alias mylog_info=’echo -ne $(/bin/date +%Y-%m-%d) $(/bin/date +%H:%M:%S) $(basename $0) $FUNCNAME $LINENO [INFO] ‘;
;;
“notice”)
alias mylog_notice=’echo -ne $(/bin/date +%Y-%m-%d) $(/bin/date +%H:%M:%S) $(basename $0) $FUNCNAME $LINENO [NOTICE] ‘;
;;
“warn”)
alias mylog_warn=’echo -ne $(/bin/date +%Y-%m-%d) $(/bin/date +%H:%M:%S) $(basename $0) $FUNCNAME $LINENO [WARN] ‘;
;;
“debug”)
alias mylog_debug=’echo -ne $(/bin/date +%Y-%m-%d) $(/bin/date +%H:%M:%S) $(basename $0) $FUNCNAME $LINENO [DEBUG] ‘;
;;
“error”)
alias mylog_error=’echo -ne $(/bin/date +%Y-%m-%d) $(/bin/date +%H:%M:%S) $(basename $0) $FUNCNAME $LINENO [ERROR] ‘;
;;
“echo”)
alias mylog_echo=’echo ‘;
;;
*)
;;
esac
done
2 使用
[cpp] view plain copy
#!/bin/bash
# ########################################################
# Filename: checkrun.sh
# Description:
# 验证 mylog 的用法
# Example:
# ########################################################

source /etc/mylog log debug error info notice warn echo

function check_apache()
{
#xxx;
mylog “normal running\n”;
}

function check_mysql()
{
#xxx;
mylog_debug “normal running\n”;
}

function check_nginx()
{
#xxx;
mylog_error “normal running\n”;
}

function check_squid()
{
#xxx;
mylog_info “normal running\n”;
}

function check_varnish()
{
#xxx;
mylog_notice “normal running\n”;
}

function check_tomcat()
{
#xxx;
mylog_warn “normal running\n”;
}

function check_myprog()
{
#xxx;
mylog_echo “normal running”;
}

function check_all()
{
check_apache;
check_mysql;
check_nginx;
check_squid;
check_varnish;
check_tomcat;
check_myprog;
}

check_all;

3 运行结果
[php] view plain copy
$> ./checkrun.sh
2012-09-21 16:03:04 checkrun.sh check_apache() 15 normal running
2012-09-21 16:03:04 checkrun.sh check_mysql() 21 [DEBUG] normal running
2012-09-21 16:03:04 checkrun.sh check_nginx() 27 [ERROR] normal running
2012-09-21 16:03:04 checkrun.sh check_squid() 33 [INFO] normal running
2012-09-21 16:03:04 checkrun.sh check_varnish() 39 [NOTICE] normal running
2012-09-21 16:03:04 checkrun.sh check_tomcat() 45 [WARN] normal running
normal running

4 调试
你可以根据打印的日志信息定位错误, 如
[php] view plain copy
2012-09-21 16:03:04 checkrun.sh check_nginx() 27 [ERROR] normal running
是说: 在 2012-09-21 16:03:04 执行脚本 checkrun.sh 的 check_nginx() 函数 在第 27 行左右发生了错误.

Good luck.

分类: Shell脚本编程 标签:

Shell标准输出、标准错误 >/dev/null 2>&1

2015年8月28日 评论已被关闭

Shell标准输出、标准错误 >/dev/null 2>&1
http://blog.sina.com.cn/s/blog_4aae007d010192qc.html
eg:sudo kill -9 `ps -elf |grep -v grep|grep $1|awk ‘{print $4}’` 1>/dev/null 2>/dev/null

命令的结果可以通过%>的形式来定义输出

/dev/null 代表空设备文件
> 代表重定向到哪里,例如:echo “123” > /home/123.txt
1 表示stdout标准输出,系统默认值是1,所以”>/dev/null”等同于”1>/dev/null”
2 表示stderr标准错误
& 表示等同于的意思,2>&1,表示2的输出重定向等同于1

那么本文标题的语句:
1>/dev/null 首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。
2>&1 接着,标准错误输出重定向等同于 标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。
/////////////////////
脚本只使用标准输入、标准输出和标准错误

Shell会自动为我们打开和关闭0、1、2这三个文件描述符,我们不需要显式地打开或关闭它们。标准输入是命令的输入,默认指向键盘;标准输出是命令的输出,默认指向屏幕;标准错误是命令错误信息的输出,默认指向屏幕。

如果没有显式地进行重定向,命令通过文件描述符0从屏幕读取输入,通过文件描述符1和2将输出和错误信息输出到屏幕。但如果我们想从其他文件(再次强调,I/O设备在Unix/Linux中也是文件)读取输入或产生输出,就需要对0、1、2使用重定向了。其语法如下:
command < filename 把标准输入重定向到filename文件中
command 0< filename 把标准输入重定向到filename文件中

command > filename 把标准输出重定向到filename文件中(覆盖)
command 1> fielname 把标准输出重定向到filename文件中(覆盖)

command >> filename 把标准输出重定向到filename文件中(追加)
command 1>> filename 把标准输出重定向到filename文件中(追加)

command 2> filename 把标准错误重定向到filename文件中(覆盖)
command 2>> filename 把标准输出重定向到filename文件中(追加)

command > filename 2>&1 把标准输出和标准错误一起重定向到filename文件中(覆盖)
command >> filename 2>&1 把标准输出和标准错误一起重定向到filename文件中(追加)

command < filename >filename2 把标准输入重定向到filename文件中,把标准输出重定向

到filename2文件中
command 0< filename 1> filename2 把标准输入重定向到filename文件中,把标准输出重定向

到filename2文件中

重定向的使用有如下规律:

1)标准输入0、输出1、错误2需要分别重定向,一个重定向只能改变它们中的一个。
2)标准输入0和标准输出1可以省略。(当其出现重定向符号左侧时)
3)文件描述符在重定向符号左侧时直接写即可,在右侧时前面加&。
4)文件描述符与重定向符号之间不能有空格!

分类: Shell脚本编程 标签: