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

2016- Shell细小问题汇总

2016-05-23 13:21 417 查看

Shell细小问题汇总

目录(?)[+]

Shell细小问题汇总

Shell细小问题汇总
使用find查找文件
grep查找文件内容
if 多条件组合判断示例
Linux系统时间设置
在远程节点上推送命令时需要特别注意和
sudo -i和su -l的差异分析
关于 varrun和pid
文件测试参数汇总
字符串测试参数汇总
如何正确传递数组参数
批量修改文件名
配置163 yum repo的脚本
关于devnull 21devnull
标准输入输出和错误
变量的字符串操作
变量的字符串操作示例
后台运行nohup
条件测试test

条件测试

预定义的变量

使用find查找文件

基本格式:find path expression

1.按照文件名查找

    (1)find / -name httpd.conf  #在根目录下查找文件httpd.conf,表示在整个硬盘查找

    (2)find /etc -name httpd.conf  #在/etc目录下文件httpd.conf

    (3)find /etc -name ‘srm’  #使用通配符*(0或者任意多个)。表示在/etc目录下查找文件名中含有字符串‘srm’的文件

    (4)find . -name ‘srm*’   #表示当前目录下查找文件名开头是字符串‘srm’的文件

2.按照文件特征查找     

    (1)find / -amin -10   # 查找在系统中最后10分钟访问的文件(access time)

    (2)find / -atime -2   # 查找在系统中最后48小时访问的文件

    (3)find / -empty   # 查找在系统中为空的文件或者文件夹

    (4)find / -group cat   # 查找在系统中属于 group为cat的文件

    (5)find / -mmin -5   # 查找在系统中最后5分钟里修改过的文件(modify time)

    (6)find / -mtime -1   #查找在系统中最后24小时里修改过的文件

    (7)find / -user fred   #查找在系统中属于fred这个用户的文件

    (8)find / -size +10000c  #查找出大于10000000字节的文件(c:字节,w:双字,k:KB,M:MB,G:GB)

    (9)find / -size -1000k   #查找出小于1000KB的文件

3.使用混合查找方式查找文件

    参数有: !,-and(-a),-or(-o)。

    (1)find /tmp -size +10000c -and -mtime +2   #在/tmp目录下查找大于10000字节并在最后

    (2)find / -user fred -or -user george   #在/目录下查找用户是fred或者george的文件文件

    (3)find /tmp ! -user panda  #在/tmp目录中查找所有不属于panda用户的文件

grep查找文件内容

基本格式:grep -r strToFind /target/dir

1.主要参数

    -c:只输出匹配行的计数。

    -i:不区分大小写

    -h:查询多文件时不显示文件名。

    -l:查询多文件时只输出包含匹配字符的文件名。

    -n:显示匹配行及行号。

    -s:不显示不存在或无匹配文本的错误信息。

    -v:显示不包含匹配文本的所有行。

 2.pattern正则表达式主要参数:

 

    \: 忽略正则表达式中特殊字符的原有含义。

    ^:匹配正则表达式的开始行。

    $: 匹配正则表达式的结束行。

    \<:从匹配正则表达 式的行开始。

    >:到匹配正则表达式的行结束。

    [ ]:单个字符,如[A]即A符合要求 。

    [ - ]:范围,如[A-Z],即A、B、C一直到Z都符合要求 。

    .:所有的单个字符。

    * :有字符,长度可以为0。

 3.实例 

  (1)grep ‘test’ d*  #显示所有以d开头的文件中包含 test的行

  (2)grep ‘test’ aa bb cc    #显示在aa,bb,cc文件中包含test的行

  (3)grep ‘[a-z]{5}’ aa   #显示所有包含每行字符串至少有5个连续小写字符的字符串的行

  (4)grep magic /usr/src  #显示/usr/src目录下的文件(不含子目录)包含magic的行

  (5)grep -r magic /usr/src  #显示/usr/src目录下的文件(包含子目录)包含magic的行

  (6)grep -w pattern files :只匹配整个单词,而不是字符串的一部分(如匹配’magic’,而不是’magical’)

if 多条件组合判断示例

<code class="hljs bash has-numbering"><span class="hljs-keyword">if</span> [ ! <span class="hljs-string">"<span class="hljs-variable">$STARTUP_TARGET</span>"</span> = <span class="hljs-string">"all"</span> <span class="hljs-operator">-a</span> ! <span class="hljs-string">"<span class="hljs-variable">$STARTUP_TARGET</span>"</span> = <span class="hljs-string">"hadoop"</span> <span class="hljs-operator">-a</span> ! <span class="hljs-string">"<span class="hljs-variable">$STARTUP_TARGET</span>"</span> = <span class="hljs-string">"spark"</span> ]
<span class="hljs-keyword">then</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"STARTUP_TARGET is invalid or not specified!"</span>
<span class="hljs-keyword">exit</span> <span class="hljs-number">1</span>
<span class="hljs-keyword">fi</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>

注意:对于if来说,后面紧跟的“[”实际上是test命令的别名!所以后续的表达式都是test命令的参数,所以才会需要:

“[“右侧要加一个空格再跟参数
“=”两侧都需要有空格
否则参数就连在了一起,变成了一个参数!

Linux系统时间设置

修改时区

很多系统在安装时没有设置时区,这样很多系统默认就会使用统一协调时UTC来显示时间,使用date来查看一下输出时间就知道时区和时间是否正确了(如果是UTC表示是统一协调时,非本地时区,如果是CST表示中国标准时间,意味着时区已经正常)。通常,时间不正确多是只因为时区问题导致的,所以我们只需修改系统的时区就可以了,方法是把本地(中国上海)的时区文件覆盖到/etc/localtime即可:
<code class="hljs perl has-numbering">cp /usr/share/zoneinfo/Asia/Shanghai /etc/<span class="hljs-keyword">localtime</span></code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

2.修改ls -l的时间格式

<code class="hljs avrasm has-numbering">vim /etc/profile<span class="hljs-preprocessor">.d</span>/time_style<span class="hljs-preprocessor">.sh</span>
<span class="hljs-keyword">add</span>
export TIME_STYLE=<span class="hljs-string">"+%F %T"</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul>

在远程节点上推送命令时需要特别注意$!和$?

<code class="hljs bash has-numbering">ssh -T root@hdcoe01<<EOF
su <span class="hljs-operator">-l</span> hive -c <span class="hljs-string">"nohup <span class="hljs-variable">$HIVE_HOME</span>/bin/hive --service metastore -hiveconf hive.log.file=hive-metastore.log \
-hiveconf hive.log.dir=<span class="hljs-variable">$HIVE_LOG_DIR</span>><span class="hljs-variable">$HIVE_LOG_DIR</span>/hive-metastore.out 2><span class="hljs-variable">$HIVE_LOG_DIR</span>/hive-metastore.log &"</span>
su <span class="hljs-operator">-l</span> hive -c <span class="hljs-string">"echo $!|cat><span class="hljs-variable">$HIVE_PID_DIR</span>/hive-metastore.pid"</span>
EOF</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>

上述脚本中
$!
的值永远是当前主机或者说是本地shell下上一次后台程序的PID,而不可能是前一次推送的
hive --service metastore
的PID!

sudo -i和su -l的差异分析

<code class="hljs lasso has-numbering">ssh <span class="hljs-attribute">-T</span> root@<span class="hljs-variable">$NAME_NODE</span><span class="hljs-subst"><<</span>EOF
sudo <span class="hljs-attribute">-i</span> <span class="hljs-attribute">-u</span> <span class="hljs-variable">$HDFS_USER</span> <span class="hljs-variable">$HADOOP_HOME</span>/bin/hdfs namenode <span class="hljs-attribute">-format</span> <span class="hljs-attribute">-force</span>
EOF
sudo: sorry, you must have a tty <span class="hljs-keyword">to</span> run sudo</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>

此错误需要通过visudo来修改相关配置,若改为:

<code class="hljs lasso has-numbering">ssh <span class="hljs-attribute">-T</span> root@<span class="hljs-variable">$NAME_NODE</span><span class="hljs-subst"><<</span>EOF
su <span class="hljs-attribute">-l</span> <span class="hljs-variable">$HDFS_USER</span> <span class="hljs-attribute">-c</span> <span class="hljs-string">"$HADOOP_HOME/bin/hdfs namenode -format -force"</span>
EOF</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul>

则没有问题,总结起来:su -l要比sudo -i方便好用!

补充:虽然使用 su很方便,不过缺点是,当我的主机是多人共管的环境时,如果大家都要使用 su 来切换成为 root 的身份,那么每个人都得要知道 root 的口令,这样口令太多人知道可能会流出去,很不妥当呢!怎办?透过 sudo 来处理即可!相对于 su 需要了解新切换的用户口令 (常常是需要 root 的口令), sudo 的运行则仅需要自己的口令即可! 甚至可以配置不需要口令即可运行 sudo 呢!

关于 /var/run和pid

Well since /var/run is mounted as tmpfs. That means it’s totally empty when your machine boots and it’s meant to be like this to prevent stuff like daemons not starting because of a left-over PID-file.

Startup scripts usually create the directories they need before using them. If you want to store a PID-file either put it in /var/run directly or create a directory before creating the PID-file. This is no place to store data that needs to remain there across
reboots.

/var/run是linux约定应用程序存放pid文件的地方(现在大多数系统已经改为了/run,然后把/var/run改为软连接指向了/run),这并非是一个特殊的文件夹,linux也不会强制应用程序把PID放在这里,只是说这是一个“约定的,默认的”存放PID文件的位置!这个文件夹唯一特殊的地方在于:在当前大多数的Linux系统下,它被挂载为了tmpfs分区,这意味:只要系统重启,文件夹内的所有数据都会清空
首先我们需要明白:PID文件本身和Linux操作系统没有必然关系,它的产生和使用都是应用程序自已来负责的!一般来说,规范的应用程序在启动时会到指定的文件夹下查找自己的PID文件,如果文件存在说明程序正在运行中,就终止当前的启动程序,并给出提示信息!如果不存在,才继续进行启动。当程序关闭时,也会自己删除PID文件!当然,以上说的是“规范”的应用程序,有的程序并不一定按照这样的规范操作,这就需要具体情况具体分析了。

文件测试参数汇总



字符串测试参数汇总



如何正确传递数组参数

<code class="hljs bash has-numbering"><span class="hljs-shebang">#!/bin/sh</span>
<span class="hljs-function"><span class="hljs-title">t</span></span>()
{
nodeList=<span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-variable">${nodeList[*]}</span>
}
a=(<span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span>)
t <span class="hljs-variable">${a[*]}</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul>

输出: 1

<code class="hljs bash has-numbering"><span class="hljs-shebang">#!/bin/sh</span>
<span class="hljs-function"><span class="hljs-title">t</span></span>()
{
nodeList=<span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-variable">${nodeList[*]}</span>
}
a=(<span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span>)
t <span class="hljs-string">"<span class="hljs-variable">${a[*]}</span>"</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul>

输出: 1 2 3

批量修改文件名

比如:将/etc/yum.repos.d下的CentOS的yum repo文件统一添加bak后缀:

<code class="hljs mel has-numbering"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-variable">$(</span><span class="hljs-keyword">ls</span> CentOS-<span class="hljs-variable">*)</span>; <span class="hljs-keyword">do</span> mv <span class="hljs-variable">$i</span> <span class="hljs-variable">$i</span>.bak;done</code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

配置163 yum repo的脚本

<code class="hljs mel has-numbering">cd /etc/yum.repos.d
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-variable">$(</span><span class="hljs-keyword">ls</span> CentOS-<span class="hljs-variable">*)</span>; <span class="hljs-keyword">do</span> mv <span class="hljs-variable">$i</span> <span class="hljs-variable">$i</span>.bak;done
wget http:<span class="hljs-comment">//mirrors.163.com/.help/CentOS6-Base-163.repo</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul>

关于”>/dev/null 2>&1”,”>&/dev/null”

<code class="hljs bash has-numbering">id user >&/dev/null
<span class="hljs-keyword">if</span> [$? != <span class="hljs-number">0</span> ]
<span class="hljs-keyword">then</span>
useradd <span class="hljs-operator">-s</span> /sbin/nologin <span class="hljs-variable">$user</span>
<span class="hljs-keyword">fi</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>

上面是一段判断用户是否存在,如果不存在就添加用户的脚本,其中>&/dev/null 等同于 >/dev/null 2>&1 而>/dev/null 2>&1又等同于1>/dev/null 2>&1,它们的意思是一样的,即:将标准输出(也就是代表标准输出的文件1)重定向到/dev/null(即不打印标准输出信息),然后把标准错误输出(也就是代表标准错误输出的文件2)合并(也就是&符号的含义)重定向到标准输出,这样,最终达到的效果或者说是目地为:舍弃命令执行中输出的所有信息(不打印任何信息)!

在POSIX shell中,命令的结果可以通过%>的形式来定义(其中%表示文件描述符:1为标准输出stdout、2为标准错误stderr)!系统默认%值是1,也就是1>,而1>可以简写为>,也就是默认为>。

>&/dev/null
这是对
>/dev/null 2>&1
的一个缩写!

标准输入、输出和错误

当我们在shell中执行命令的时候,每个进程都和三个打开的文件相联系,并使用文件描述符来引用这些文件。由于文件描述符不容易记忆, shell同时也给出了相应的文件名。下面就是这些文件描述符及它们通常所对应的文件名:

文件文件描述符
输入文件—标准输入0
输出文件—标准输出1
错误输出文件—标准错误2
系统中实际上有12个文件描述符,但是正如我们在上表中所看到的, 0、1、2是标准输入、

输出和错误。可以任意使用文件描述符3到9。

变量的字符串操作



变量的字符串操作示例

file=/dir1/dir2/dir3/my.file.txt

我们可以用${}分别替换获得不同的值:

${file#*/}:拿掉第一条/及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:拿掉最后一条/及其左边的字符串:my.file.txt
${file#*.}:拿掉第一个.  及其左边的字符串:file.txt
${file##*.}:拿掉最后一个.  及其左边的字符串:txt
${file%/*}:拿掉最后条/及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:拿掉第一条/及其右边的字符串:(空值)
${file%.*}:拿掉最后一个.  及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}:拿掉第一个.  及其右边的字符串:/dir1/dir2/dir3/my
${file:0:5}:提取最左边的5个字节:/dir1
${file:5:5}:提取第5个字节右边的连续5个字节:/dir2
${file/dir/path}:将第一个dir替换为path:/path1/dir2/dir3/my.file.txt
${file//dir/path}:将全部dir替换为path:/path1/path2/path3/my.file.txt

记忆的方法为:

#是去掉左边(在鉴盘上#在$之左边)
%是去掉右边(在鉴盘上%在$之右边)
单一符号是最小匹配﹔两个符号是最大匹配

后台运行nohup…&

Unix/Linux下一般比如想让某个程序在后台运行,很多都是使用& 在程序结尾来让程序自动运行。比如我们要运行MySQL在后台:

/usr/local/mysql/bin/mysqld_safe –user=mysql &

但是加入我们很多程序并不象mysqld一样做成守护进程,可能我们的程序只是普通程序而已,一般这种程序使用& 结尾,但是如果终端关闭,那么程序也会被关闭。但是为了能够后台运行,那么我们就可以使用nohup这个命令,比如我们有个test.php需要在后台运 行,并且希望在后台能够定期运行,那么就使用nohup:

nohup /root/test.php &

条件测试:test,[ ]

shell中的测试条件有三种:test,[ ]以及(( ))。其中test和[ ]是等价的,”[“实际上只是test命令的一个别名而已!这也是 [ 之后必须有空格的原因。因此将二者归为一类讨论。

[ ]

[ ]的测试对象有三种:

字符串 ,如
[ -z str ]


数字,如
[ n1 -lt n2 ]


文件,如
[ -f filename ]


[ ]内的变量,最好用双引号包括; 中括号内的常量,最好用单引号或双引号包括,例如

<code class="hljs bash has-numbering"><span class="hljs-keyword">if</span> [ -z <span class="hljs-variable">${var}</span> ]  <span class="hljs-comment">#可能出错  </span>
<span class="hljs-keyword">if</span> [ -z <span class="hljs-string">"<span class="hljs-variable">${var}</span>"</span> ]  <span class="hljs-comment">#最好改成这样  </span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li></ul>

-a(与)和-o(或):进行多重条件的复合测试,如

<code class="hljs bash has-numbering"><span class="hljs-keyword">if</span> [ -n <span class="hljs-string">"<span class="hljs-variable">${var}</span>"</span> <span class="hljs-operator">-a</span> <span class="hljs-string">"<span class="hljs-variable">${var}</span>"</span> <span class="hljs-operator">-lt</span> <span class="hljs-number">100</span> ] <span class="hljs-comment">#当变量被定义且其值小于100时</span></code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

取反测试!:对测试条件取反

<code class="hljs bash has-numbering"><span class="hljs-keyword">if</span> [ ! <span class="hljs-string">"$?"</span> <span class="hljs-operator">-eq</span> <span class="hljs-string">"0"</span> ]  <span class="hljs-comment">#上一条命令返回值不等于0  </span></code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

条件测试:(( ))

1.(( ))作测试条件用时其中可使用类C的数字测试条件,包括

<code class="hljs asciidoc has-numbering">< :小于
> :大于
<= :小于等于
>= :大于等于
<span class="hljs-header">== :等于</span>
!= :不等于</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>

2.经测试,(( ))中不能用-a,-o以及!等复合测试

3.(( ))除用作数值测试之外,还可用于变量自增减,如(( var++ ))

预定义的变量

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  shell linux