简述:这篇总结是在360企业安全实习第一周学到的。
Linux中的 2>&1 、if文件命令 、tr 、$0等相关参数含义的用法
1. 2>&1
command>/dev/null 2>&1 &这样形式的命令。首先我们把这条命令大概分解下首先就是一个nohup表示当前用户和系统的回话下的进城忽略响应HUP消息。&是把该命令以后台的job的形式运行。那么就剩下command>/dev/null 2>&1,command>/dev/null较好理解,/dev/null表示一个空设备,就是说吧command的执行结果重定向到空设备中,说白了就是不显示任何信息。那么2>&1又是什么含义?
command>a 2>a 与 command>a 2>&1的区别
通过上面的分析,对于command>a 2>&1这条命令,等价于command 1>a 2>&1可以理解为执行command产生的标准输入重定向到文件a中,标准错误也重定向到文件a中。那么是否就说command 1>a 2>&1等价于command 1>a 2>a呢。其实不是,command 1>a 2>&1与command 1>a 2>a还是有区别的,区别就在于前者只打开一次文件a,后者会打开文件两次,并导致stdout被stderr覆盖。&1的含义就可以理解为用标准输出的引用,引用的就是重定向标准输出产生打开的a。从IO效率上来讲,command 1>a 2>&1比command 1>a 2>a的效率更高。
几个基本符号及其含义
/dev/null 表示空设备文件
0 表示stdin标准输入
1 表示stdout标准输出
2 表示stderr标准错误
从command>/dev/null说起
其实这条命令是一个缩写版,对于一个重定向命令,肯定是a > b这种形式,那么command > /dev/null难道是command充当a的角色,/dev/null充当b的角色。这样看起来比较合理,其实一条命令肯定是充当不了a,肯定是command执行产生的输出来充当a,其实就是标准输出stdout。所以command > /dev/null相当于执行了command 1 > /dev/null。执行command产生了标准输出stdout(用1表示),重定向到/dev/null的设备文件中。
说说2>&1
通过上面command > /dev/null等价于command 1 > /dev/null,那么对于2>&1也就好理解了,2就是标准错误,1是标准输出,那么这条命令不就是相当于把标准错误重定向到标准输出么。等等是&1而不是1,这里&是什么?这里&相当于等效于标准输出。这里有点不好理解,先看下面。
举个栗子
来个shell
//test.sh
#!/bin/sh
t
date
chmod +x test.sh为test.sh增加执行权限。这里我们弄了两条命令,其中t指令并不存在,执行会报错,会输出到stderr。date能正常执行,执行会输出当前时间,会输出到stdout。
执行./test.sh > res1.log结果为
我们发现stderr并没有被重定向到res1.log中,stderr被打印到了屏幕上。这也进一步证明了上面说的./test.sh > res1.log等价于./test.sh 1>res1.log
执行./test.sh>res2.log 2>&1结果为
这次我们发现stdout和stderr都被重定向到了res2.log中了。上面我们未对stderr也就是2说明如何输出,stderr就输出到了屏 幕上,这里我们不仅对stdout进行说明,重定向到res2.log中,对标准错误也进行了说明,让其重定向到res2.log的引用即 res2.log的文件描述符中。
再思考一下
为何2>&1要写在command>1的后面,直接用2可以么。比如ls 2>a。其实这种用法也是可以的,ls命令列出当前的目录,用stdout(1)表示,由于这个时候没有stderr(2),这个时候执行ls 2>a也会正常产生一个a的文件,但是a的文件中是空的,因为这时候执行ls并没有产生stderr(2)。
在阅读《Shell脚本学习指南》时,看到这么一段代码
- if [ -f "$file" ] && ! [ -w "$file" ]
- then
- # $file存在且为一般文件,但不可写入
- echo $0: $file is not writable, giving up. >&2
- exit 1
- fi
但是对>&2的含义不是很明白,于是就上网查了一下,整理如下
>&2
也就是把结果输出到和标准错误一样;之前如果有定义标准错误重定向到某file文件,那么标准输出也重定向到这个file文件。
其中&的意思,可以看成是“The same as”、“与...一样”的意思
shell上:
0表示标准输入
1表示标准输出
2表示标准错误输出
> 默认为标准输出重定向,与 1> 相同
2>&1 意思是把 标准错误输出 重定向到 标准输出.
&>file 意思是把 标准输出 和 标准错误输出 都重定向到文件file中
用例子说话:
1. grep da * 1>&2
2. rm -f $(find / -name core) &> /dev/null
上面两例中的 & 如何理解,&不是放到后台执行吗?
牛解:
1.&>file或n>&m均是一个独立的重定向符号,不要分开来理解。
2.明确文件和文件描述符的区别。
3.&>file表示重定向标准输出和错误到文件
例如:
rm -f $(find / -name core) &> /dev/null,/dev/null是一个文件,这个文件比较特殊,所有传给它的东西它都丢弃掉。
4.n>&m表示使文件描述符n成为输出文件描述符m的副本。这样做的好处是,有的时候你查找文件的时候很容易产生无用的信息,如:2> /dev/null的作用就是不显示标准错误输出;另外当你运行某些命令的时候,出错信息也许很重要,便于你检查是哪出了毛病,如:2>&1
例如:
注意,为了方便理解,必须设置一个环境使得执行grep da *命令会有正常输出和错误输出,然后分别使用下面的命令生成三个文件:
grep da * > greplog1
grep da * > greplog2 1>&2
grep da * > greplog3 2>&1 //grep da * 2> greplog4 1>&2 结果一样
#查看greplog1会发现里面只有正常输出内容
#查看greplog2会发现里面什么都没有
#查看greplog3会发现里面既有正常输出内容又有错误输出内容
|
在POSIX shell中,命令的结果可以通过%>的形式来定义(其中%表示文件描述符:1为标准输出stdout、2为标准错误stderr)!系统默认%值是1,也就是1>,而1>可以简写为>,也就是默认为>。而stdout的默认目标是终端(这点不用验证吧)。另外,stderr的默认目标我个人认为也是终端,比如:
#abcddcba
sh: abcddcba: not found.
错误信息显示在终端上(对于telnet、dtterm等,那就说虚拟终端了)。
==============实验环境==============
#mkdir redtest
#cd redtest
#mkdir a4
#touch a1 a2 a3
==============简单试验==============
#ls >redout.lst (等同于ls 1>redout.lst,标准输出重定向)
系统先执行>redout.lst,生成一个空文件,然后系统执行ls,再把结果重定向到redout.lst。这时在终端看不到任何信息,但是#more redout.lst可以看到a1、a2、a3、a4和redout.lst。
#./ourgame 2>rederr.lst (标准错误重定向)
因为系统找不到执行脚本ourgame,产生错误,但并不是显示在终端上,而是把错误信息重定向到了rederr.lst。
#more rederr.lst
sh: ourgame: not found.
==============组合试验==============
#rm rederr.lst
#rm redout.lst
#vi conj
#!/usr/bin/sh
for FN in `ls`
do
if [[ -f $FN ]]
then
echo $FN
else
cp $FN $FN.new
fi
done
//conj的作用是执行以后产生标准输出(echo)和标准错误(cp)
#chmod 755 conj
看看一下命令的结果:
#./conj
a1 //stdout
a2 //stdout
a3 //stdout
cp: a4: is a directory. Need "-R" option.//stderr
conj //stdout
再试试重定向的结果:
(1)、输出重定向到文件a1,终端上只能看到标准错误:
#./conj >a1
#./conj 1>a1
#more a1
a1
a2
a3
conj
(2)错误重定向到文件a1,终端上只能看到标准输出:
#./conj 2>a1
#more a1
cp: a4: is a directory. Need "-R" option.
(3)把标准输出和标准错误都重定向到a1,终端上看不到任何信息:
是否能这么写呢:
# ./conf >a1 2>a1
正确的做法应该是:
#./conf >a1 2>&1 (等同于#./conf 1>a1 2>&1)
#more a1
a1
a2
a3
cp: a4: is a directory. Need "-R" option.
conj
//其中&的意思,可以看成是“The same as”、“与...一样”的意思。本例中就是2>和1>一样,都输出到a1中。
再看一个例子:
#./conj 2>&1 >a1
同样可以解释为2>和1>一样,但是这时1>是系统默认输出到终端,所以标准错误也输出到终端;然后,系统把标准输出重定向到文件a1。
2.if 文件表达式
if [ -f file ] 如果文件存在
if [ -d ... ] 如果目录存在
if [ -s file ] 如果文件存在且非空
if [ -r file ] 如果文件存在且可读
if [ -w file ] 如果文件存在且可写
if [ -x file ] 如果文件存在且可执行
整数变量表达式
if [ int1 -eq int2 ] 如果int1等于int2
if [ int1 -ne int2 ] 如果不等于
if [ int1 -ge int2 ] 如果>=
if [ int1 -gt int2 ] 如果>
if [ int1 -le int2 ] 如果<=
if [ int1 -lt int2 ] 如果<
字符串变量表达式
If [ $a = $b ] 如果string1等于string2
字符串允许使用赋值号做等号
if [ $string1 != $string2 ] 如果string1不等于string2
if [ -n $string ] 如果string 非空(非0),返回0(true)
if [ -z $string ] 如果string 为空
if [ $sting ] 如果string 非空,返回0 (和-n类似)
shell的if与c语言if的功能上的区别
shell if |
c语言if |
0为真,走then |
正好相反,非0走then |
不支持整数变量直接if
必须:if [ i –ne 0 ]
但支持字符串变量直接if
if [ str ] 如果字符串非0
|
支持变量直接if
if (i )
|
1 要将命令行运行的结果保存到文件中,truncate模式下使用 >,append模式下使用 >>
2 要将文件中的内容作为标准输入,应使用 <:
3 ps(process status)命令用来查看当前系统中运行着哪些进程,常用命令:
4 "|" 是Linux下的管道命令,对命令 cmd1 | cmd2,解释为将cmd1的STDOUT作为cmd2的STDIN来执行.
(每个Linux命令运行时都会打开三个文件,文件描述符0代表stdin,1代表stdout,2代表stderr)
5 grep(global regular expression print, 全局正则表达式输出),用于查询,例如:
6 /dev/null文件是一个特殊的文件,将输出重定向到这里,写入的内容全都会被丢弃,从这里读取,什么也读不到.
常用于实现"禁止输出"的功能.
3.tr命令
tr(选项)(参数)
-c或——complerment:取代所有不属于第一字符集的字符;
-d或——delete:删除所有属于第一字符集的字符;
-s或--squeeze-repeats:把连续重复的字符以单独一个字符表示;
-t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。
参数
字符集1:指定要转换或删除的原字符集。当执行转换操作时,必须使用参数“字符集2”指定转换的目标字符集。但执行删除操作时,不需要参数“字符集2”;
字符集2:指定要转换成的目标字符集。
实例
将输入字符由大写转换为小写:
echo "HELLO WORLD" | tr 'A-Z' 'a-z'
hello world
'A-Z' 和 'a-z'都是集合,集合是可以自己制定的,例如:'ABD-}'、'bB.,'、'a-de-h'、'a-c0-9'都属于集合,集合里可以使用'\n'、'\t',可以可以使用其他ASCII字符。
使用tr删除字符:
echo "hello 123 world 456" | tr -d '0-9'
hello world
将制表符转换为空格:
字符集补集,从输入文本中将不在补集中的所有字符删除:
echo aa.,a 1 b#$bb 2 c*/cc 3 ddd 4 | tr -d -c '0-9 \n'
1 2 3 4
此例中,补集中包含了数字0~9、空格和换行符\n,所以没有被删除,其他字符全部被删除了。
用tr压缩字符,可以压缩输入中重复的字符:
echo "thissss is a text linnnnnnne." | tr -s ' sn'
this is a text line.
巧妙使用tr做数字相加操作:
echo 1 2 3 4 5 6 7 8 9 |
xargs -n1 | echo $[ $(tr '\n' '+') 0 ]
删除Windows文件“造成”的'^M'字符:
cat
file | tr -s "\r" "\n" > new_file
或
cat file | tr -d "\r" > new_file
tr可以使用的字符类:
[:alnum:]:字母和数字
[:alpha:]:字母
[:cntrl:]:控制(非打印)字符
[:digit:]:数字
[:graph:]:图形字符
[:lower:]:小写字母
[:print:]:可打印字符
[:punct:]:标点符号
[:space:]:空白字符
[:upper:]:大写字母
[:xdigit:]:十六进制字符
使用方式:
tr '[:lower:]' '[:upper:]'
4.$?相关含义
$0 这个程式的执行名字
$n 这个程式的第n个参数值,n=1..9
$* 这个程式的所有参数,此选项参数可超过9个。
$# 这个程式的参数个数
$$ 这个程式的PID(脚本运行的当前
进程ID号)
$! 执行上一个背景指令的PID(后台运行的最后一个进程的
进程ID号)
$? 执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误)
$- 显示shell使用的当前选项,与set命令功能相同
$@ 跟$*类似,但是可以当作数组用
- Hadoop Shell命令大全
hadoop支持命令行操作HDFS文件系统,并且支持shell-like命令与HDFS文件系统交互,对于大多数程序猿/媛来说,shell-like命令行操作都是比较熟悉的,其实这也是Hadoop的极大 ...
- Shell命令和流程控制
Shell命令和流程控制 在shell脚本中可以使用三类命令: 1)Unix 命令: 虽然在shell脚本中可以使用任意的unix命令,但是还是由一些相对更常用的命令.这些命令通常是用来进行文件和文字 ...
- 在程序中执行shell命令
在linux系统下的操作中我们会经常用到shell命令来进行,一开始学习进程的时候对于shell命令也进行了思考,认为shell命令就是一个进程的外壳,经过了后来的学习对于这一点也有了更多的认识. 用 ...
- Linux远程执行Shell命令或脚本
## 远程执行shell命令 ssh [user]@[server] '[command]' # eg. ssh root@192.168.1.1 'uptime' ## 远程执行本地shell脚本 ...
- HBase基本shell命令
HBase基本shell命令 以下shell命令都是经过测试,正常展示,若有不足,还望指点! 1.创建表 create ‘表名称’,‘列族名称1’,‘列族名称1’create 'test_M_01', ...
- Linux SHELL 命令入门题目答案(一)
1.如何使用shell 打印 “Hello World!” (1)如果你希望打印 !,那就不要将其放入双引号中,或者你可以通过转义字符转义(2)echo 'hello world!' 使用单引号ech ...
- Linux SHELL 命令入门题目(一)
新年新气象,注重知识积累,提高手敲代码能力,而不是眼高手低,只会复制黏贴. 1.使用shell 打印 “Hello World!” 2.求变量'hello world'的字符长度 3.$0 .$SHE ...
- shell命令获取最新文件的名称
最近有一个需求,在部署游戏战场服时,从程序包到部署需要做一些本地化的操作,手工操作费时费力,故写一个shell脚本,一键部署. 遇到的问题是每次要部署最新的程序包,因此需要shell命令获取最新的文件 ...
- 【转】Hadoop FS Shell命令
FS Shell 调用文件系统(FS)Shell命令应使用 bin/hadoop fs <args> 的形式. 所有的的FS shell命令使用URI路径作为参数.URI格式是scheme ...
- [蟒蛇菜谱] Python封装shell命令
# -*- coding: utf-8 -*- import os import subprocess import signal import pwd import sys class MockLo ...
随机推荐
- Adobe RIA 开发工程师认证考试大纲
AdobeRIA 开发工程师认证考试大纲 考题数量:共90道题,考试通过正确率:60% 考试时间:120分钟 试题种类:单选题.多选题和判断题 1. Adobe RIA基础知识(2道题) ...
- VS2005、vs2008+WinXPDDK+DDKWizard配置驱动开发环境
所需软件下载地址如下(均为有效资源链接,速度都比较可以): vs2005: http://221.224.22.210/downloadsawyer/VS.Net2005简体中文版.rar wi ...
- 芝麻HTTP:在阿里云上测试Gerapy教程
1.配置环境 阿里云的版本是2.7.5,所以用pyenv新安装了一个3.6.4的环境,安装后使用pyenv global 3.6.4即可使用3.6.4的环境,我个人比较喜欢这样,切换自如,互不影响. ...
- SpringMVC_第一个程序
一.基本代码的完成 补充 1.在myeclipse中 WEB-INF下放的资源和WebRoot下的资源区别: WEB-INF下放到资源是不能通过浏览器直接访问的,是比较安全的,只能是后台服务端程序进行 ...
- freemarker获取封装类中对象的属性(六)
freemarker获取封装类中对象的属性 1.设计思路 (1)封装学生类 (2)创建数据模型 (3)新建student.ftl (4)运行Junit测试文件,生成HTML文件 2.封装学生类 Stu ...
- visual studio 2010 Error: IntelliSense: identifier "DWORD" is undefined
在自己工程里,添加别的工程文件时,出现改错误 解决方法 在文件前添加: using namespace std; 参考: http://www.programgo.com/article/502412 ...
- zookeeper选举
什么时候开始进行选举 1.服务器初始化启动的时候2.服务器运行期间连接不上leader的时候 初始化选举过程 进行leader选举至少需要两台服务器,我们这里举例为5台服务器(1,2,3,4,5)1. ...
- WebView的使用--Hybrid App
App页面是运行在WebView中的,一个App页面对应一个WebView,本例实现两个WebView之间的跳转. 实现过程(用到了MUI框架): 1.页面标识+跳转按钮(index.html.mai ...
- MinGW安装和使用
P.S.安装MinGW主要是code blocks 编译出现了这个问题: ERROR: You need to specify a debugger program in the debuggers' ...
- testng及JMeter使用之初体验
这里只是简单的说下我再项目中使用testng的JMeter使用的情况, 主要的是使用JMeter的体验, 都是以截图和文字为说明的. 1, 性能测试之testng 直接可以 ...