Linux Shell 笔记

1、查看进程的环境变量

普通:$cat /proc/1642/environ 
换行:$cat /proc/1642/environ | tr '\0' '\n'
tr的命令格式是tr SET1 SET2,凡是在SET1中的字符,都会被替换为SET2中相应位置上的字符。

2、SHELL脚本赋值与等于判断

赋值:$var=value
相等:$var  = value
在赋值时不要留有空格。

3、从进程名字得知进程ID

$ pgrep my_proc 

4、当前环境变量

$PATH
记住必须是大写
输出BASH路径:$echo $SHELL
注意不要在*.sh文件里定义名为PATH的变量,否则会导致后面的命令无法执行,因为PATH被更换掉了。
修改环境变量:
export PATH=/home/work/cswuyg/:$PATH
export命令可以打印出所有的环境变量信息

5、查看文件

alias ll='ls -l' ; ll等同于ls -l
查看隐藏文件:
隐藏属性的文件的文件名以“点”开头
ls -al 
查看普通文件:
ls -l
按时间排序:
ll -t;   ll -rt (时间从小到大)
查看文件名含有某些字符的文件:
ll *active*03-24*.origin -rt
按文件大小排序:
ls -l |sort -n  

6、bash中的双引号和单引号的不同

shell脚本:
count=9              
fruit=apple          
echo "we hava $count${fruit}s"     
其中fruit是字符串变量, 如果双引号换成单引号那就导致fruit输出错误。
加上大括号{}是因为后面有其他字符串,需要做隔开。
shell中的单引号、双引号、反引号:
单引号:所有转义符全部关闭,完整的反应括号中的内容
双引号:部分转义符关闭,但某些则保留(如:$ )
反引号:反引号内作为一个系统命令并执行

7、shell脚本中的括号

两层小括号
((exp)),两层括号表明里面的是整数型运算,如:
- a=10;((a++));echo $a   
- for ((i=0;i<5;i++));do echo $i;done  
中括号
中括号等同于test;也可以用来引用数组元素。
- test功能举例:
  a=10;if [ $a = '10' ];then echo 'a==10';fi 
- 数组元素引用举例:
  array[1]=world
  array[0]=hello
  for k in ${!array[@]};do echo ${array[${k}]};done
双中括号[[]]也有test的功能,而且比单个中括号更通用。
大括号
可以:扩展;代码块;替换;匹配;取字符
 - 扩展举例:
  touch {a,b}.txt : 创建a.txt和b.txt
  echo {0..4} : 输出0 1 2 3 4
- 代码块举例:
  { a=10;b=20;};echo $a 
- 字符串替换举例:
  A=${c:-NULL};echo $A  :如果c变量不存在,则A被赋值为NULL,否则就是c变量的值。
  A=${c:+NULL};echo $A  :  如果c变量存在,则A被赋值为NULL,否则就是c变量原来的值(不存在)。
上例子中的NULL可以换成其它的字符串
- 字符串匹配举例:
   temp=${file%.*} #右到左匹配,留下不匹配的
   log_date=${temp##*_} #左到右贪婪匹配,留下不匹配的
   两个%或者两个#都表示贪婪匹配。
- 取字符
     input=0123;echo ${input:0:3}  输出: 012
 

8、给予脚本可执行属性

$ chmod a+x script.sh
在执行的时候必须带上:./  指明是在当前目录
注意shell脚本的开头行需要指定脚本执行程序: #!/bin/bash     

9、shell脚本中的条件语句

if [ $UID -ne 0 ]
then echo xxx
else echo yyy
fi
注意,"["后边有空格,"]"前面有空格。
数字比较:数字小于:-lt;数字等于:-eq;数字大于:-gt
判断一个文件是否存在
if [ -f $FILEPATH ]
then
  xxxx
fi
if [ $UU_FILE_NUM -gt 0 ] && [ ! -f ${UU_DEST} ]    # 并列条件语句
...
判断目录是否存在:
if [ ! -d "glog_log" ]
then
    echo "create"
    mkdir glog_log
fi
判断某一类文件是否存在:
思路,获取这一类文件的文件个数,判断是否大于0
UU_ORG=*active*
UU_FILE_NUM=`ls ${UU_ORG} |wc -l`
if [ $UU_FILE_NUM -gt 0 ] 
then 
...
fi
---
-ne —比较两个参数是否不相等
-lt —参数1是否小于参数2
-le —参数1是否小于等于参数2
-gt —参数1是否大于参数2
-ge —参数1是否大于等于参数2
-f — 检查某文件是否存在(例如,if [ -f "filename" ])
-d — 检查目录是否存在
 
判断目录是否存在,不存在则创建:
if [ ! -d "glog_log" ]
then
    echo "Create glog_log"
    mkdir glog_log
fi

10、拷贝文件

本地目录拷贝:
cp -ri sourcedir  deskdir
scp远程文件拷贝:
scp intersection.exe work@xxxxhost:/home/disk2/cswuyg
将intersection.exe从本机当前目录拷贝到远程xxxxhost机器的/home/disk2/cswuyg目录。
目录拷贝,加上: -r
把文件从远程拷贝到本地
scp root@11.111.1.1:/home/work/cswuyg.test /home/work
注意:scp需要输入远端机器密码
拷贝文件同时也拷贝它的时间:cp -p  

11、压缩/解压

zip压缩:
zip -r a.zip /home/disk9/cswuyg
r 表示循环压缩/home/disk9/cswuyg目录下的文件。
解压:unzip a.zip -d dest
tar+gzip压缩:
tar -zcvf a.tar.gz .  
-z 使用gzip来压缩tar文件
-v 显示文件的归档进度
-c 创建一个新的归档
-f 与c选项一起使用时,创建的tar文件使用该选项指定的文件名;与x一起使用时,解除该选项指定的归档。
 
压缩某类文件:
tar -zcvf a.tar.gz /home/cswuyg/2014-04-08*
解压到dest目录:
tar -xzvf a.tar.gz -C dest
-j 使用bzip压缩:
tar -jcvf a.temp .
 
bz2格式文件夹解压
bzip2 -d protobuf-2.5.0.tar.bz2
tar -xf protobuf-2.5.0.tar 
 
把不同目录下的文件tar到一个包里面:
对打进tar中的文件去除根目录:tar --transform 's|.*/||g' -zcvvf my.tar.gz a b bb/c   
transform跟着换名规则。
资料:
cat filelist | xargs tar -rvf archive.tar --transform='s|.*/||g'
transform可以改变被压缩文件在tar包中的名字。

12、删除文件/目录

rm -r 目录名
rm -rf 加上-f 不做删除提示
删除带有特殊字符的文件:
先用 ls -i 得到 1 hello world 的inod(就是最前面的数字)假设这个数字是102141122 ,然后
find . -inum 102141122 -exec rm {} \; 就可以删除了。
结合find删除有某些特征的文件:
find . -name "*.log" -ctime +7 | xargs rm -f # 删除文件变更时间为7天之前且文件名以.log结尾的文件
atime:访问时间(access time),指的是文件最后被读取的时间,可以使用touch命令更改为当前时间;
ctime:变更时间(change time),指的是文件本身最后被变更的时间,变更动作可以使chmod、chgrp、mv等等;
mtime:修改时间(modify time),指的是文件内容最后被修改的时间,修改动作可以使echo重定向、vi等等;

13、并发启动多进程

只需要在shell脚本的每行后面加上 “&” 符号。
譬如:
./uu_all.exe 2014-03-20 1 > uu_old_2014-03-20.txt &
./uu_all.exe 2014-03-21 1 > uu_old_2014-03-21.txt &

14、linux系统定时任务

crontab -l  查询linux的定时任务,可以使用crontab设置定时启动某个监控进程
crontab -e 打开该文件进行编辑
譬如:
00 23 * * * /home/disk11/timer_bak.sh > /home/disk11/bak_timer.log
表明在每天23:00 执行timer_bak.sh。
前面的5个*号位分别表示:分钟(0~59),小时(0~23),天(1~31),月份(1~12),工作日(0~6)。
星号(*)指定该命令在每个时间阶段执行,譬如,如果小时位置是*,则表示这个命令每小时执行一次。
如果是要指定第5、第10分钟执行该命令,那么就在分钟位置上写明:5,10,中间用都逗号分隔。
如果要指定每3分钟执行一次,那么就是在分钟位置上写:*/3  这表示遇到能被3整除的分钟时间时执行该命令。

15、shell下的日期

ye=`date --date='yesterday' +%Y-%m-%d`
echo $ye 
这里显示格式为:2014-04-08
或者:
ye=`date --date='1 days ago' +%Y-%m-%d`
打出更详细的时间
date "+%G-%m-%d %H:%M:%S"

16、输出重定向

重定向是 > ,会覆盖旧数据。
重定向累加是 >> ,不会覆盖旧数据。
 如:python a.py > a.log

17、kill 进程

先 ps -ef | xxx  看xxx进程情况
找到第二列,就是进程号 ,输入 kill  进程号,如果要强杀,则在kill后面加上-9.
批量杀进程方法1:ps -ef|grep "./xxx.sh" |grep -v grep|cut -c 9-15|xargs kill
批量杀进程方法2:ps + awk 
ps -ef|grep "dbpath=/home/cswuyg/shard1" | grep -v grep | awk '{print$2;}' |xargs kill 
杀掉所有进程名为uwsgi的进程:killall uwsgi

18、查看linux版本

    1)uname -a  : 内核版本信息
    2)cat /proc/version   :  内核版本信息
    3)cat /etc/issue    :  发行版本信息
    4)lsb_release -a  :   发行版本信息

19、查看磁盘IO

以MB为单位,每5秒钟刷新一次输出:iostat -xtm 5
%util 表明磁盘使用率
rMB/s   表示磁盘读取
wMB/s 表示磁盘写入
 

20、vim下dos格式文件转为unix格式文件

在windows下编辑的shell脚本,拿到linux下无法运行,或者运行错误,很可能是由于编码问题,需要转换为unix编码,vim下的命令:
:set fileformat=unix 或者 :set ff=unix

21、wget拉取数据

 wget xxxhost:/home/disk8/cswuyg/uu_2014-04-14.txt
局域网内速度可以达到110MB/s,比scp快很多。
wget最多只能使用后缀通配符,无法使用更高级的通配符。
指定保存文件名:
MAC_REMOTE_MID=远程ftp路径
MAC_LOCAL_MID=本地保存路径
wget ${MAC_D_MID} -O ${MAC_LOCAL_MID}
 
需要wget版本大于1.10.*版本,需要 ProFTPD 版本大于1.2.6 ,否则不能拉取大于2G的文件。
一个wget去掉层级目录的例子:
wget -r -nH --cut-dirs=2 ftp://xxxhost:/home/disk1/cswuyg/2014-04-04.tar.gz
下载之后,会在本地创建cswuyg目录,并把文件下载到该目录下。
wget拉取文件失败可能是因为远程文件权限不足,需要设置被拉取的文件的根目录:chmod 755 xxx。

22、shell字符串匹配分割

(1) %  从右到左匹配,如${var%.*},从右边到左边匹配var变量,发现第一个.,就把.右边被匹配了的删除,剩下.左边的
(2) # 从左到右匹配,如$(var#*\), 发现第一个\,就把左边的删除,包括\。
demo:
shell文件,a.sh
a='1234.56&789' 
printf ${a%.*}
printf "\n" 
printf ${a#*&}
printf "\n" 
printf $a

输出:

1234
789
1234.56&789
%% 表示从右到左贪婪匹配
## 表示从左到右贪婪匹配
demo:
shell文件,a.sh
a='1.2.34&56&789'
printf ${a%%.*}
printf "\n" 
printf ${a##*&}                                                                                                                                     
printf "\n" 
printf $a 

输出:

1
789
1.2.34&56&789

23、查看磁盘空间大小

du -c -h --max-depth=1
du -h --max-depth=1 本目录下,所有文件的size,--max-depth表示递归深度为1、
du -c -h *log 查看某类文件大小

24、shell下的通配符

如果在shell下执行命令时,参数里面出现了*、?等通配符,这时候参数会是很多个,会把目录下的所有符合通配符的文件统统作为参数。
这种对于python的处理非常方便,python收到的就是一个list。

25、查看这个进程当前打开了哪些文件

lsof -p [pid]
or:
ls -l /proc/[pid]/fd/

26、修改文件的群组

work权限的用户无法操作root权限的文件,所以需要把那些文件的群组从root修改为work。
修改disk0举例:
先登陆root:su root
然后,递归修改:chown -R work disk0

27、读取文件

#!/bin/bash
while read line
do            
    echo $line
done < xx.sh   
 
如果不是采用while,而是采用for:
for word in `cat bak_config`
do
  echo $word
done
那么,单个单词也会被当作行输出。

28、查看命令的可执行程序所在磁盘位置

which ftp
或者使用 type ftp

29、查看进程的启动位置、可执行文件位置

譬如查找Mongo进程的信息:
ps -ef|grep mongo 得到进程ID,
可执行程序位置: ll /proc/2764/exe  
启动目录:ll /proc/2764/cwd
打开了哪些文件:
某个进程打开了哪些文件:ls -l /proc/[pid]/fd/

30、find命令查找文件

 find / -name inotify.h  表示从根目录开始查找inotify.h文件。
find . -maxdepth 1 -name "@*"   这个命令意思是,查找当前目录下以@开头的文件或者目录,搜索深度为一级也就是只在当前目录找,不进入子目录。
查找当前目录下的b开头的文件夹下的以.tgz结尾的文件
find . -name b* -type d -exec ls *.tgz \; 
或者:
find . -name b* -type d -exec find *.tgz \; 
如果有错,也许这样子才可以(多了一个魔术字符串{}):
find . -name 'b*' -type d -exec find {} -name '*.tgz' \; 
搜索文本内容:
从根目录开始查找所有扩展名为.log的文本文件,并找出包含”ERROR”的行:
find / -type f -name "*.log" | xargs grep "ERROR"
打印出包含这特定字符串的文件名:find .|xargs grep -ri "logxxx" -l   
批量文件批量替换文本:
查找个数:
find .  -type f -name '*.*' | xargs sed -n '/2013-2014/p'
xx换为yy:
find . -type f -name '*.*' | xargs sed -i 's/xx/yy/g'
find . -type f ! -path '*temp_bak*' | xargs sed -n 's/xx/yy/g'
find . -name '*.*' | xargs  perl -pi -e 's|old|new|g'
显示出所有包含xx的内容:find . -name '*.*' -type f | xargs sed -n '/xx/p'

31、查看glibc的版本

方法1:ldd --version; ldd是glibc的一部分,所以它的版本也就是glibc的版本;
方法2:rpm -qa | grep glibc; 在centos下查看安装了哪些个glibc相关的包;
方法3:ls -l /lib/libc.so.6; 查看libc.so.6指向哪个具体的libc so版本;
方法4:调用C函数获取:
#include <gnu/libc-version.h>      
#include <iostream>                                                                                                                                                                              
int main(void)
{
    std::cout << gnu_get_libc_version() << std::endl;
    return 0;
}
注意:网络上有些人把glibc版本跟gcc版本混在一起了:glibc是Linux版的C语言运行时库,而GCC是编译工具。

32、查看Linux Shell操作历史

vi  ~/.bash_history

33、文件链接

ln [参数][源文件或目录][目标文件或目录]
 
软链接:
ln -s log2013.log link2013
结果:
link2013 -> log2013.log
硬链接:
ln log2013.log link2013
会产生一个一样大小的文件,它们的链接数都会加1

34、crontab下的输出重定向到/dev/null

crontab里的输出,会被放到邮件缓存处,如果输出非常大可能导致tmp磁盘用尽,解决办法,把输出放弃掉,也就是重定向到/dev/null:

0 4 * * * xxxcmd >/dev/null 2>&1

2>&1 表示将标准错误输出也输出到标准输出中。

标准输入:0;标准输出:1;标准错误输出:2。

35、使用bc做计算

echo 10 + 20 |bc
输出:30

36、查看ELF文件依赖的so库

ldd XXX.exe
查看所加载的库:
LD_DEBUG=files ./xxx.exe
LD_DEBUG可以修改为其它:
bindings 显示动态链接符号绑定过程
versions 显示符号的版本依赖关系
查看so的导出函数:
nm -D 7z.so
objdump -tT 7z.so

37、./mongod启动出现崩溃解决方法

Floating point exception (core dumped)
解决方法:
 LD_DEBUG=libs ./bin/mongod -v    查看所有的加载库,看在哪里崩溃了。
最后发现是libc版本跟官网上编译出来的版本不兼容导致的。

38、awk里的if

ps -ef|grep mongo |awk '{if($9=="mongo"){print$9;print$2}}'  
含义:把所有mongo进程grep出来,然后以空格、tab键分割,第9个字符串如果是mongo,则输出第9个字符串、第2个字符串。

39、shell取字符串的前12位

a_str=${line:0:12}
或者,玩玩awk:
mac_str=(`echo $line |awk '{$a=substr($0, 0, 12);print($a);}'`)

40、利用iconv实现数据编码转换

iconv -c -f unicode -t gb2312 cswuyg*2014-06-17_9.origin > /home/work/a.tmp
-c 表示忽略乱码
-f 表示源文件编码
-t 表示目标文件编码

41、ulimit -a

显示当前所有资源的限制:
如:
open files                      (-n) 10240

42、根据IP拿到域名/根据域名拿到IP

host 10.242.92.26 ; 可以得到域名;
host xxxhost ; 可以得到IP;   

43、使用rz\sz上传\下载文件

在secureCRT下,使用rz -bye 上传文件;
sz 下载文件
rz和sz无法使用时
yum install lrzsz

44、chmod 755是什么意思

你可以在linux终端先输入ls -al,可以看到如:
   -rwx-r--r-- (一共10个参数)
第一个跟参数跟chmod无关,先不管.
2-4参数:属于user
5-7参数:属于group
8-10参数:属于others
接下来就简单了:r==>可读 w==>可写 x==>可执行
               r=4 w=2 x=1
所以755代表 rwxr-xr-x

45、使用sendmail发送邮件

[cswuyg@xxxhost ~]$ /usr/sbin/sendmail -t << EOF
> SUBJECT: sendmail test subject
> TO: cswuygxx@xx.com
> mail content
> EOF

46、查看进程因OOM被kill掉的命令

 dmesg |grep Kill
***************
Out of memory: Kill process 24145 (python) score 637 or sacrifice child
Killed process 24145, UID 500, (python) total-vm:21423020kB, anon-rss:20930232kB, file-rss:636kB
***************
理解 OOM:
 total-vm includes both your physical RAM and swap space.

As I understand, the size of the virtual memory that a process uses is listed as total-vm. Part of it is really mapped into the RAM itself (allocated and used). This is RSS. Part of the RSS is allocated in real memory blocks (other than mapped into a file or device). This is anonymous memory (anon-rss) and there is also RSS memory blocks that are mapped into devices and files (file-rss).

So, if you open a huge file in vim, the file-rss would be high, on the other size, if you malloc() a lot of memory and really use it, your anon-rss would be high also. On the other side, if you allocate a lot of space (with malloc()), but nevers use it, the total-vm would be higher, but no real memory would be used (due to the memory overcommit), so, the rss values would be low.

简单说:

total-vm表明当前系统可以使用的内存,包括物理内存和交换区空间。

anon-rss表明当前被声明要使用的内存。

file-rss表明当前映射到磁盘文件的内存。

47、中文显示乱码

vim下的乱码,在vim下执行命令:set encoding=utf-8
SecureCRT的乱码:在~/.bash_profile添加:export LANG=zh_CN.UTF8 ,然后重新登陆。

48、linux命令行进入vim模式

在命令行中输入:set -o vi

49、查看资源占用的命令

free -g
top、uptime
sar 1 1
iostat -x 1

50、Linux系统增加用户 (只允许root执行)

useradd user1 创建一个新用户
passwd user1 修改一个用户的口令

51、查看文件系统类型,查看文件系统大小

df -T、df -h

52、readlink -f 获取完整路径

如:readlink -f flume_control
/home/cswuyg/flume/flume_control

53、批量部署时,如何修改crontab

远程执行修改crontab的shell命令行,譬如:
CMD_BEFORE_COPY = "cd /home/cswuyg/;(crontab -l > crontab_bak.20140522;crontab -l;echo '20 20 * * * find /home/cswuyg/*.pb.log -mtime +3 | xargs rm -f')|crontab"

54、mv 文件后拿着旧文件句柄的程序如何处理

在打日志的时候,可能出现这种情况:a.log重命名为a.log1,后续的日志要求写入到新的a.log文件。
如果有个进程拿着旧文件的句柄在写日志,通过mv对文件重命名完之后,虽然文件名改了,但是那个句柄还是有效的,还是在继续写旧文件。在日志写入时,如果要保证写入到新的a.log文件,代码中需要检查a.log文件inode信息是否发生改变,如果改变则重新打开文件。

55、查看Linux进程树

pstree

56、查看二进制文件内容

od -c a.txt

57、查看网卡流量

(1) watch more /proc/net/dev
(2)watch -n 1 '/sbin/ifconfig eth0|grep bytes'  
显示:
Every 1.0s: /sbin/ifconfig eth0|grep bytes                                                                                                                                                Fri Jun 12 10:41:08 2014
          RX bytes:72289863517 (67.3 GiB)  TX bytes:161966405143 (150.8 GiB)
 RX 为下行流量(接收) TX 为上行流量(发送)

58、统计端口连接数量

netstat -nat | grep 27017 |awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -nr|head -20 
统计连接到27017端口的链接数

59、一秒钟的时钟滴答数,跟CPU主频无关

这个值在系统编译时设定的,如:
[work@xxxhost boot]$ cat /boot/config.`uname -r` | grep '^CONFIG_HZ=' 
CONFIG_HZ=1000
C代码获取:
printf ("_SC_CLK_TCK = %ld\n", sysconf (_SC_CLK_TCK));
但是,从配置文件里读到的跟用C++代码读到的不一样,可能用C++代码读到的更准确。

60、单个进程内存使用量的限制

配置文件:/etc/security/limits.conf

61、make并行编译

编译C/C++时的shell命令:make -j8 表示8个线程并发编译,要求makefile要写好依赖,否则可能会出现错误。

62、用shell脚本设置环境变量

shell脚本文件内容:
--------------------------------------------------
export PROTOC=/home/disk1/cswuyg/protobuf/install/bin/protoc
bash
--------------------------------------------------
最后加上bash表明新开一个子shell环境,子shell环境继承了父shell的环境变量设置,所以PROTOC有效。
如果没有最后的bash,那么脚本执行完之后,依然是没有PROTOC变量。

63、查看一个进程的线程信息

pstack [pid] | egrep -o "Thread [0-9]+ [^:]*"

64、top命令

只查看某个process name的多个进程:
top -p $(pgrep -d',' -f "xxx_process_name")

可以使用top输出到文件:

top -b -n 1 -d 1 –c > top.log

-b batch模式,可以重定向到文件中

-n 一共取2次数据

-d 每次top数据间隔为几秒

你可以做个crontab任务一分钟调用一次追加到文件中

-n -d 可以自己设置,单位是s

-c 表示显示完整命令行

top界面下的显示操作:
P :根据CPU使用百分比排序
M:根据驻留内存大小排序
1:显示各个CPU信息
c:显示完整命令行

65、交换区是否打开

free 命令,看Swap大小。

66、shell脚本的输入参数

$1是行参变量,也就是脚本执行时的第一个参数。

CHOICE=${1:-NULL}意思是当$1为空时,自动将NULL替换成$1所要带入的变量值,这里就是$CHOICE为NULL。

67、判断libstdc++支持哪些glibc库

 strings /usr/lib64/libstdc++.so.6 |grep GLIBC_ 

posted @ 2018-08-16 15:03  MR__Wang  阅读(425)  评论(0编辑  收藏  举报