Tag Archives: linux

LINUX命令xargs的简单应用及举例

xargs
大多数 Linux 命令都会产生输出:文件列表、字符串列表等。但如果要使用其他某个命令并将前一个命令的输出作为参数该怎么办?例如,file 命令显示文件类型(可执行文件、ascii 文本等);您可以处理输出,使其仅显示文件名,现在您希望将这些名称传递给 ls -l 命令以查看时间戳记。xargs 命令就是用来完成此项工作的。它允许您对输出执行其他某些命令。记住下面这个来自于第 1 部分中的语法:

file -Lz * | grep ASCII | cut -d”:” -f1 | xargs ls -ltr

让我们来剖析这个命令字符串。第一个,file -Lz *,用于查找是符号链接或者经过压缩的文件。它将输出传递给下一个命令 grep ASCII,该命令在其中搜索 “ASCII” 字符串并产生如下所示的输出:
alert_DBA102.log: ASCII English text
alert_DBA102.log.Z: ASCII text (compress’d data 16 bits)
dba102_asmb_12307.trc.Z: ASCII English text (compress’d data 16 bits)
dba102_asmb_20653.trc.Z: ASCII English text (compress’d data 16 bits)

由于我们只对文件名感兴趣,因此我们应用下一个命令 cut -d”:” -f1,仅显示第一个字段:
alert_DBA102.log
alert_DBA102.log.Z
dba102_asmb_12307.trc.Z
dba102_asmb_20653.trc.Z

现在,我们希望使用 ls -l 命令,将上述列表作为参数进行传递,一次传递一个。xargs 命令允许您这样做。最后一部分,xargs ls -ltr,用于接收输出并对其执行 ls -ltr 命令,如下所示:

ls -ltr alert_DBA102.log
ls -ltr alert_DBA102.log.Z
ls -ltr dba102_asmb_12307.trc.Z
ls -ltr dba102_asmb_20653.trc.Z

因此,xargs 本身虽然没有多大用处,但在与其他命令相结合时,它的功能非常强大。

下面是另一个示例,我们希望计算这些文件中的行数:

$ file * | grep ASCII | cut -d”:” -f1 | xargs wc -l
47853 alert_DBA102.log
19 dba102_cjq0_14493.trc
29053 dba102_mmnl_14497.trc
154 dba102_reco_14491.trc
43 dba102_rvwr_14518.trc
77122 total

(注:上述任务还可用以下命令完成:)

$ wc -l ‘file * | grep ASCII | cut -d”:” -f1 | grep ASCII | cut -d”:” -f1‘

该 xargs 版本用于阐释概念。Linux 可以用几种方法来完成同一个任务;请使用最适合您的情况的方法。

使用该方法,您可以快速重命名目录中的文件。

$ ls | xargs -t -i mv {} {}.bak

-i 选项告诉 xargs 用每项的名称替换 {}。-t 选项指示 xargs 先打印命令,然后再执行。

另一个非常有用的操作是当您使用 vi 打开要编辑的文件时:

$ file * | grep ASCII | cut -d”:” -f1 | xargs vi

该命令使用 vi 逐个打开文件。当您希望搜索多个文件并打开它们进行编辑时,使用该命令非常方便。

它还有几个选项。最有用的可能是 -p 选项,它使操作具有可交互性:

$ file * | grep ASCII | cut -d”:” -f1 | xargs -p vi
vi alert_DBA102.log dba102_cjq0_14493.trc dba102_mmnl_14497.trc dba102_reco_14491.trc dba102_rvwr_14518.trc ?…

此处的 xarg 要求您在运行每个命令之前进行确认。如果您按下 “y”,则执行命令。当您对文件进行某些可能有破坏且不可恢复的操作(如删除或覆盖)时,您会发现该选项非常有用。

-t 选项使用一个详细模式;它显示要运行的命令,是调试过程中一个非常有帮助的选项。

如果传递给 xargs 的输出为空怎么办?考虑以下命令:

$ file * | grep SSSSSS | cut -d”:” -f1 | xargs -t wc -l
wc -l
0
$

在此处,搜索 “SSSSSS” 后没有匹配的内容;因此 xargs 的输入均为空,如第二行所示(由于我们使用 -t 这个详细选项而产生的结果)。虽然这可能会有所帮助,但在某些情况下,如果没有要处理的内容,您可能希望停止 xargs;如果是这样,可以使用 -r 选项:
$ file * | grep SSSSSS | cut -d”:” -f1 | xargs -t -r wc -l
$

如果没有要运行的内容,该命令退出。

假设您希望使用 rm 命令(该命令将作为 xargs 命令的参数)删除文件。然而,rm 只能接受有限数量的参数。如果您的参数列表超出该限制怎么办?xargs 的 -n 选项限制单个命令行的参数个数。

下面显示了如何限制每个命令行仅使用两个参数:即使向 xargs ls -ltr 传递五个文件,但每次向 ls -ltr 仅传递两个文件。

$ file * | grep ASCII | cut -d”:” -f1 | xargs -t -n2 ls -ltr
ls -ltr alert_DBA102.log dba102_cjq0_14493.trc
-rw-r—– 1 oracle dba 738 Aug 10 19:18 dba102_cjq0_14493.trc
-rw-r–r– 1 oracle dba 2410225 Aug 13 05:31 alert_DBA102.log
ls -ltr dba102_mmnl_14497.trc dba102_reco_14491.trc
-rw-r—– 1 oracle dba 5386163 Aug 10 17:55 dba102_mmnl_14497.trc
-rw-r—– 1 oracle dba 6808 Aug 13 05:21 dba102_reco_14491.trc
ls -ltr dba102_rvwr_14518.trc
-rw-r—– 1 oracle dba 2087 Aug 10 04:30 dba102_rvwr_14518.trc

使用该方法,您可以快速重命名目录中的文件。

$ ls | xargs -t -i mv {} {}.bak

-i 选项告诉 xargs 用每项的名称替换 {}。

我需要将一个用.svn管理的项目改成由CVS来管理,因此,在导入整个项目到CVS中之前,我需要删除所有目录下以及子孙目录下的.svn目录及.svn目录下的的子目录和文件。我一直寻找一种最简单的方法,最后写了一个程序去干这事情。结果同事告诉我只需要一条指令就可以了:find -name ‘.svn’ |xargs rm -rf
这个教训非常惨重,我一生讨厌傻瓜,可那一刻发现自己是最大的傻瓜!

是的,虽然我们——至少是我,天天使用LINUX但是真的是在高效的使用这个系统吗?不,很多时候并没有花时间去研究它,使用一些固有愚蠢的方式和思维模式在使用这个系统。

1. 建立多级目录:

mkidr 指令用来建立目录,事实上,我们一直都是这么干的。但是在这么使用的时候我们并没有去看它的那些参数提供了哪些额外的功能.

mkidr -p /share/dragon ; 在根目录下建立share目录,并在/share目录下建立dragon目录。mkdir -p guicmd/{bin,lib,src,share/version,doc/{html,pdf,info,man}}
;用来建立一个复杂的项目目录树。

2.find 配合xargs使用:

find -name ‘.svn’ |xargs rm -rf ;这个不用说了,就是我前面提到的。
xargs更加象一个筛选器,将符合管道传递过来的文件名的内容一并处理掉,这是一个极度高效的方法。

rsync 错误与解决方案收集

问题一:
@ERROR: chroot failed
rsync error: error starting client-server protocol (code 5) at main.c(1522) [receiver=3.0.3]

原因:
服务器端的目录不存在或无权限,创建目录并修正权限可解决问题。

问题二:
@ERROR: auth failed on module tee
rsync error: error starting client-server protocol (code 5) at main.c(1522) [receiver=3.0.3]

原因:
服务器端该模块(tee)需要验证用户名密码,但客户端没有提供正确的用户名密码,认证失败。
提供正确的用户名密码解决此问题。

问题三:
@ERROR: Unknown module ‘tee_nonexists’
rsync error: error starting client-server protocol (code 5) at main.c(1522) [receiver=3.0.3]

原因:
服务器不存在指定模块。提供正确的模块名或在服务器端修改成你要的模块以解决问题。

apache mod_negotiation与MultiViews的奥妙

今天遇到一个奇怪的问题,取URL请求字符串时,明明访问的是/index/welcome/,取回来的却是/welcome/。
框架在处理这个问题时的处理流程是:

$php_self = $_SERVER[‘PHP_SELF’];
$uri = $_SERVER[‘REQUEST_URI’];

if (isset($_SERVER[‘PATH_INFO’])) {
$uri = $_SERVER[‘PATH_INFO’];
} else {
$uri = substr($uri, strlen(dirname($php_self)) );
}
$uri[0]!=’?’ || $uri = “/$uri”;
$uri = strtok($uri, ‘?’);

先判断PATH_INFO,然后再处理其他情况。
但我这里直接是http://xxx.com/index/welcome/ 怎么会存在PATH_INFO变量呢?
后来打印$_SERVER变量时发现,apache认为我访问的这个链接是/index.php/welcome/ !
原来apache可以在访问/path/foo时,如果找不到/path/foo,就会去找/path/foo.*,并且选一个合适的返回来,为你服务。
我这里存在着/index.php,所以访问/index/welcome/时,它就自动去找/index.php了!
而这些功能是一个模块提供的,它的名字叫mod_negotiation。相关说明:http://httpd.apache.org/docs/2.2/content-negotiation.html
同时,这个模块还提供了一个目录级别的控制开关,也就是

对于exec函数家族的理解

在百度快照看到这篇文章,为了保护文物,特转之留念。
原文链接:http://fenglei.blog.com.cn/archives/2005/39431.shtml (运气好的话或许还能复活。)

很早就知道了exec这个函数家族,也知道它们的作用,但是没有认真分析过它们之间的区别,也不知道该在什么时候用哪个,近来看到这里,顺便总结出来,以方便自己并方便大家。总结如下:
exec家族一共有六个函数,分别是:

int execl(const char *path, const char *arg, ……);
int execle(const char *path, const char *arg, …… , char * const envp[]);
int execv(const char *path, char *const argv[]);
int execve(const char *filename, char *const argv[], char *const envp[]);
int execvp(const char *file, char * const argv[]);
int execlp(const char *file, const char *arg, ……);

这些函数之间的
第一个区别是:
前四个取路径名做为参数,后两个取文件名做为参数,如果文件名中不包含 “/” 则从PATH环境变量中搜寻可执行文件, 如果找到了一个可执行文件,但是该文件不是连接编辑程序产生的可执行代码文件,则当做shell脚本处理。
第二个区别:
前两个和最后一个函数中都包括“ l ”这个字母 ,而另三个都包括“ v ”, ” l “代表 list即表 ,而” v “代表 vector即矢量,也是是前三个函数的参数都是以list的形式给出的,但最后要加一个空指针,如果用常数0来表示空指针,则必须将它强行转换成字符指 针,否则有可能出错。,而后三个都是以矢量的形式给出,即数组。
最后一个区别:
与向新程序传递环境变量有关,如第二个和第四个以e结尾的函数,可以向函数传递一个指向环境字符串指针数组的指针。即自个定义各个环境变量,而其它四个则使用进程中的环境变量。
exec家族虽然有六个函数,但根据函数名还是可以很容易的区别开来,简单说到这里。
本文参考一本UNIX编程书籍,很可惜我不知道书叫什么名字。

–转载结束–

我是看Beginning Linux Programming 3rd时,对这个家族的函数产生了兴趣,特百度之查明区别。下面是英文说明:

There is a whole family of related functions grouped under the exec heading. They differ in the way
that they start processes and present program arguments. An exec function replaces the current process
with a new process specified by the path or file argument.
#include
char **environ;
int execl(const char *path, const char *arg0, …, (char *)0);
int execlp(const char *file, const char *arg0, …, (char *)0);
int execle(const char *path, const char *arg0, …, (char *)0, char *const
envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
In general, using system is a far from ideal way to start other processes, because it
invokes the desired program using a shell. This is both inefficient, because a shell is
started before the program is started, and also quite dependent on the installation
for the shell and environment that are used. In the next section, we see a much better
way of invoking programs, which should almost always be used in preference to the
system call.
453
Processes and Signals
b544977 Ch11.qxd 12/1/03 8:56 AM Page 453These functions belong to two types. execl, execlp, and execle take a variable number of arguments
ending with a null pointer. execv and execvp have as their second argument an array of strings. In both
cases, the new program starts with the given arguments appearing in the argv array passed to main.
These functions are usually implemented using execve, though there is no requirement for it to be done
this way.
The functions with names suffixed with a p differ in that they will search the PATH environment variable
to find the new program executable file. If the executable isn’t on the path, an absolute file name, includ-
ing directories, will need to be passed to the function as a parameter.
The global variable environ is available to pass a value for the new program environment.
Alternatively, an additional argument to the functions execle and execve is available for passing an
array of strings to be used as the new program environment.
If we wish to use an exec function to start the ps program, we can choose from among the six exec family
functions, as shown in the calls in the code fragment that follows

Sed Skills

测试的环境:
[service@gan .ssh]$ uname -a
Linux gan 2.4.21-20.EL #1 SMP Wed Aug 18 20:34:58 EDT 2004 x86_64 x86_64 x86_64 GNU/Linux

[service@gan .ssh]$ sed -V
GNU sed version 4.0.7
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,
to the extent permitted by law.

文章出处:http://gan.cublog.cn

1>. 删除普通字符操作
[service@gan .ssh]$ cat dfile.txt
LINE1
LINE2
LINE3
LINE4
LINE5
LINE6
LINE7

删除指定行2
[service@gan .ssh]$ sed ‘2d’ dfile.txt
LINE1
LINE3
LINE4
LINE5
LINE6
LINE7
http://gan.cublog.cn
删除1到5行数据
[service@gan .ssh]$ sed ‘1,5d’ dfile.txt
LINE6
LINE7

删除除1到4行的所有行
[service@gan .ssh]$ sed ‘1,4 !d’ dfile.txt
LINE1
LINE2
LINE3
LINE4

删除1行,3行数据
[service@gan .ssh]$ sed -e ‘1d’ -e ‘3d’ dfile.txt
LINE2
LINE4
LINE5
LINE6
LINE7

删除最后一行数据
[service@gan .ssh]$ sed ‘$d’ dfile.txt
LINE1
LINE2
LINE3
LINE4
LINE5
LINE6
http://gan.cublog.cn
删除3到最后一行
[service@gan .ssh]$ sed ‘3,$d’ dfile.txt
LINE1
LINE2

删除包含4字符的行
[service@gan .ssh]$ sed ‘/4/’d dfile.txt
LINE1
LINE2
LINE3
LINE5
LINE6
LINE7
[service@gan .ssh]$ sed -e ‘/4/d’ dfile.txt
LINE1
LINE2
LINE3
LINE5
LINE6
LINE7

———————
[service@gan .ssh]$ cat dfile.txt
LINE1
LINE2
LINE3http://gan.cublog.cn
LINE4
LINE5
LINE6
LINE7
ABC123
123XXABC
W00–

删除包含4,5字符的行
[service@gan .ssh]$ sed ‘/4/,/5/’d dfile.txt #这种做法不建议使用,因为有时候会不行
LINE1
LINE2
LINE3
LINE6
LINE7
ABC123
123XXABC
W00–
[service@gan .ssh]$ sed ‘/4/d;/5/d’ dfile.txt
LINE1
LINE2
LINE3
LINE6
LINE7
ABC123
123XXABC
W00–
http://gan.cublog.cn
删除开头字符为A和包含5字符的行
[service@gan .ssh]$ sed -e “/^A/d;/5/d” dfile.txt
LINE1
LINE2
LINE3
LINE4
LINE6
LINE7
123XXABC
W00–

这样操作产生的结果不知道是什么,很奇怪的结果
[service@gan .ssh]$ sed -e “/^A/,/5/d” dfile.txt
LINE1
LINE2
LINE3
LINE4
LINE5
LINE6
LINE7

删除空行(用上正侧表达式了)
[service@gan .ssh]$ sed -e ‘/^$/d’ dfile.txt

2>. 特殊字符的删除
[service@gan .ssh]$ cat sp.txt
A”/`!B\C’*<>&%#@~()?{}|+_-=:;K 1
A/`!B\C’*<>&%#@~()?{}|+_-=:;K 2
A`!B\C’*<>&%#@~()?{}|+_-=:;K 3
A!B\C’*<>&%#@~()?{}|+_-=:;K 4
AB\C’*<>&%#@~()?{}|+_-=:;K 5
ABC’*<>&%#@~()?{}|+_-=:;K 6
ABC*<>&%#@~()?{}|+_-=:;K 7
ABC<>&%#@~()?{}|+_-=:;K 8
ABC>&%#@~()?{}|+_-=:;K 9
ABC&%#@~()?{}|+_-=:;K 10
ABC%#@~()?{}|+_-=:;K 11
ABC#@~()?{}|+_-=:;K 12
ABC@~()?{}|+_-=:;K 13
ABC~()?{}|+_-=:;K 14
ABC()?{}|+_-=:;K 15
ABC)?{}|+_-=:;K 16
ABC?{}|+_-=:;K 17
ABC{}|+_-=:;K 18
ABC}|+_-=:;K 19
ABC|+_-=:;K 20
ABC+_-=:;K 21
ABC_-=:;K 22
ABC-=:;K 23
ABC=:;K 24
ABC:;K 25
ABC;K 26
ABCK 27

[service@gan .ssh]$ sed ‘/”/d’ sp.txt
A/`!B\C’*<>&%#@~()?{}|+_-=:;K 2
…… 其他的行省略不写了

[service@gan .ssh]$ sed ‘/\//d’ sp.txt
A`!B\C’*<>&%#@~()?{}|+_-=:;K 3
…… 采用转义字符\
http://gan.cublog.cn
[service@gan .ssh]$ sed ‘/`/d’ sp.txt
A!B\C’*<>&%#@~()?{}|+_-=:;K 4
……
[service@gan .ssh]$ sed ‘/!/d’ sp.txt
AB\C’*<>&%#@~()?{}|+_-=:;K 5
……
[service@gan .ssh]$ sed ‘/\\/d’ sp.txt
ABC’*<>&%#@~()?{}|+_-=:;K 6
…… 采用转义字符\
[service@gan .ssh]$ sed “/’/d” sp.txt
ABC*<>&%#@~()?{}|+_-=:;K 7
…… 使用””符号
[service@gan .ssh]$ sed ‘/*/d’ sp.txt
ABC<>&%#@~()?{}|+_-=:;K 8
…… 后面的其他字符(<>&%#@~()?{}|+_-=:;)同普通字符删除操作一样

对于sed在字符删除部分写的可能还不是很全面,慢慢添加吧。。。

Debian NO_PUBKEY error

aptitude update 是Debian下用得最多的命令之一了,但这个命令有个毛病,还是会报错,往往向人不知道如何处理。

如:

W: GPG error: http://ftp.us.debian.org stable/non-US Release: The following signatures couldn’t be verified because the public key is not available: NO_PUBKEY F1D53D8C4F368D5D
W: You may want to run apt-get update to correct these problems

看文字,是说找不到公钥,更新失败。它的建议是使用apt-get update来解决问题,但恰恰这个问题就是这个命令导致的,呵呵。因为apt-get update和aptitude update是基本类似的。aptitude是替代apt-*的新版工具罢了。

Google后,发现有类似问题的人巨多。常见的解决方案是:

# apt-get install gnupg
# gpg –keyserver wwwkeys.eu.pgp.net –recv-keys F1D53D8C4F368D5D
# gpg –armor –export F1D53D8C4F368D5D | apt-key add –

这里的F1D53D8C4F368D5D是错误信息中的那一串。

但是据我测试,这里的关键,wwwkeys.en.pgp.net这个地址,有时并无法正常使用。下面是我收集的一些keyservers,持续更新中。

wwwkeys.eu.pgp.net

pgpkeys.mit.edu

Update 2009/12/31:
更加优雅的解决方案:
apt-get install debian-archive-keyring debian-keyring

ubuntu 9.04 screenshot

今天有点兴致,就给ubuntu升级到了9.04。
目前比较少用ubuntu了,新版本的发布也不太了解了,呵呵。不过今天升级成功后,发现自己很喜欢那个登录界面!ubuntu的界面真是一个版本比一个版本漂亮!

无线网络
无线网络

发一个登录界面的截图:

gmd登录界面截图
gmd登录界面截图

附上ubuntu登录界面的截图方法:

chvt 7; sleep 9; XAUTHORITY=/var/lib/gdm/:0.Xauth DISPLAY=:0.0 import -window root /home/sp/gdm-shot.png

想要记住这么长的命令不容易,可以先把它写到一个bash文件,再用root身份执行。

screenshot.sh文件内容:

#!/bin/bash
chvt 7;
sleep 9;
XAUTHORITY=/var/lib/gdm/:0.Xauth DISPLAY=:0.0 import -window root /home/sp/gdm-shot.png

#—END OF FILE—

执行它:

chmod +x screenshot.sh
./screenshot.sh

或者直接更简单的方法:

cat > tmp
chvt 7; sleep 9; XAUTHORITY=/var/lib/gdm/:0.Xauth DISPLAY=:0.0 import -window root /home/sp/gdm-shot.png

// 这里按CTRL+D结束编辑

# sudo su
# eval `cat tmp`

当然tmp文件也可以用其他编辑器创建!

–EOF–

Linux 时区问题

安装完系统发现时间与现实时间相差+8小时,经分析由以下产生。
我们在安装时选择的是上海,而centos5把bios时间认为是utc时间,所以+8小时给我们。这个时候的bios的时间和软件的时间是不一致的。一个代表 utc 一个代表我们设置的cst(+8时区)。
我们要做的调整是:
1、vi /etc/sysconfig/clock   
 
ZONE="Asia/Shanghai"
UTC=false                          (主要是这个选项,设置硬件时钟不是跟utc一致)
ARC=false
 
2、linux的时区设置为  上海
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
 
 
3、对准时间
ntpdate 192.43.244.18
 
 
4、设置硬件时间和软件时间的一致并校准
 
/sbin/hwclock –systohc
 
 
这样我们的linux软件和计算机硬件都是cst时间了--并且是我们设置的上海时区
 
 
有什么问题参考以下两篇文章: