在学习使用ubuntu等各种喜他构建服务器的过程中遇到很多问题,意识到只是跟着网络的教程没办法管理好一个完整的应用部署和运行。遂开始学习linux基本知识,以应对服务器常见问题和软件的使用和维护。
shell
望文生义,大概意思是一个外壳,包裹着内核,能够解析用户输入的命令转化为执行的程序交给内核。
shell的种类很多,比如bash,ksh,使用C语言编写,指的是一种命令解释程序,同时也是一种解释型程序设计语言。
内置命令和外置命令:
cd,pwd这种属于内置命令,
ls其实是外置的命令,实际调用的命令在/bin/ls中。
当在命令行中显示#号时,说明处于超级用户状态,否则为*,代表普通用户。
命令行的格式
command -option arguments
命令 选项 参数
ls -a
ls -l
ls -al
ls -al /etc
ls -l /etc;cp 123.txt 123.txt
mv a.txt\
b.txt
参数可以有多个,可以多语句一行也就可以多行组成一条语句。
通配符
用于描述字符串,方便用户使用命令。
ls -a *.txt
cp /var/* /opt
ls -l /etc/*/*.conf
分别是对应什么样子的操作:
列出当前目录下以.txt结尾的文件
在/var目录下,复制所有文件到/opt目录
列出etc目录下所有子目录中的.conf类型文件
其余通配符有? [],分别对应单个任意字符和任意一个在方括号内的字符。
shell的输入输出和重定向
linux下系统打开的三个文件:标准输入,标准输出和标准错误输出。
wc < /etc/a.txt
wc << aa
somethinghere
aa
这就是输入重定向,把文件里的内容输入给wc命令代替我们键盘输入,或者是使用<<将aa与aa间隔符号之间的文本输入给wc。当然aa可以是bb也可以是其他字符。
输出重定向就是反着来,把命令的输出交给文本文件。
ps -ef > ps.txt
cat a.txt b.txt c.txt >all.txt
如果不想覆盖原有文件可以使用>>操作符。
ps -ef >> ps.txt
cat a.txt b.txt c.txt >>all.txt
错误重定向:除了标准输入和标准输出的重定向,还有错误输出和错误输入的重定向,也就是只有在命令执行出现错误的时候会输出的信息将去往我们定义的地方。使用的是2>和2>>。
ps -ef 2> ps.txt
cat a.txt b.txt c.txt 2>>all.txt
管道
什么叫管道,简而言之就是把命令连接起来,用上一个命令的输出作为下一个命令的输入。
ls -l /etc|more
ps -ef|grep httpd|wc -l
转义字符
对所有解释型语言程序来说,不可避免存在符号与文本或者字符串内的标点产生混淆,这时候转移字符就出现了。
/可以使后续的字符不被看成特殊字符,例如abc/?就会被看做一个abc?的字符串,而不会把问号作为一个通配符。包括参数中的:,?号,当然某些符号是不被允许作为文件名的一部分的。
‘’单引号的作用就是忽视内部的特殊字符和转义字符。
""双引号的作用类似单引号,但是没有忽视其中的$,`,\。
他们分别对应变量,命令执行和转义符号。
不过还有更多的用法,比如$(),${}这类,分别和反引号类似以及和$类似,但是在具体使用时有一些区别,$()内部可以叠加更多的命令。${}则是有分隔符可以区分我们的变量和其他字符文本。
str=`ls -l`
str2=`wc \` ls -l \` `
str3=$(ls -l)
str4=$(wc$(ls -l))
echo $str1 /n $str2
注意,这里叠加使用命令的输入相当于作为参数或者说我们输入的字符使用,而不是类似于重定向。这里会发现叠加ls -l的输出给wc命令作为后续参数会导致wc命令识别到代表-r权限的这一字符从而报错:没有对应的选项,反观重定向,就会正常的输出内容里的统计数据了。
基础运维命令
解压缩
tar
归档和解除归档文件的基础命令。这里只要知道是这个命令可以解压就可以了,具体的参数和选项可以查阅资料。
tar -cvf /etc/myzip.zip /etc
这一句的操作为,把/etc目录的文件全部打包到myzip文件,-c创建新的文件,-v显示所有归档文件的名称,以及我们的-f参数代表紧接着要给出存储路径的选项,必须作为该命令最后一个选项(因为后面要跟归档的文件存储设备或者路径)。
能做到按照时间选择要打包的文件,也能做到按照文件名单独排除文件,当然了也是允许使用通配符的。
解压操作只要在选项里使用-x即可,意味从对应文件中还原出归档文件。
tar -zxvf /etc/myzip.zip /etc
-z选项代表中间使用了gzip程序,进行解压或者压缩,前面的归档不等于压缩。-j代表使用bzip2程序。
允许我们解压到指定目录,包括只解压部分文件。
tar -zxvf myzip.tar.gz foder/mylog -C /myname/dir/
gzip
一个单纯的解压,压缩命令,注意只能处理文件,就算输入目录也会压缩目录下的文件而不保留目录。
gunzip是gzip的硬链接,我们不多说。
gzip [选项] 解/压缩的文件名
-d解压,-r递归式压缩对应目录,-t检查完整性,-v显示解压/压缩的文件详细名称。
-num指定压缩级别,默认为-6,
gzip -d等于gunzip命令。
zip命令也是压缩。
zip -r /etc/etcbak.zip /etc
gzip -9v /etc/etcbak.zip.gz
上面就是做了两次压缩处理。
gzip -l /etc/etcbak.zip.gz
显示压缩文件所有信息
gzip -d /etc/etcbak.zip.gz
解压文件
bzip2
bzip -9vk mydir.zip myzip1.zip myzip2.zip
之后会生成对应的mydir.zip.bz2,myzip1.zip.bz2,myzip2.zip.bz2
-f覆盖要生成的文件名同名文件
-k保留压缩源文件
-d为解压缩选项。
文件检索
find
find pathname [options] [-print -exec -ok 命令 {} \;]
选项:
-name 'myfile.*'
-lname 'myfile.*'
-gid n
-uid n
-empty
-type 文件类型
-mtime +n/-n
-path ''
-group ''
-depth
-prune
-size n
-user ''
格式如上,对应的功能分别是:
查询对应名字的文件,可使用通配符。
查询对应名称的链接文件,可使用通配符
查询用户组id为n的文件
查询用户id为n的文件
查询为空的文件
查询指定文件类型的文件 这里的文件类型可以是b,c,f,l,d,p,s,分别对应块文件,字符设备文件,普通文件,链接文件,目录,管道,socket文件。
根据时间查询,+n代表n天以前,-n代表n天之前到现在,也就是以n天以前为节点。
根据路径字符串匹配
根据用户组字符串匹配
要求先查找当前目录文件
要求跳过对应目录文件,在与-depth同时使用的情况下是被忽略的选项
查找对应大小的文件
按照用户匹配字符串查找
命令中-print代表将查找结果输出到标准输出,-exec代表对查找到的文件执行后续的命令,{}代表刚刚查询到的文件。}和\之间要有空格,要以;结尾。-ok会询问用户是否执行后续命令。
find / \( -path /var/log -o -path /usr/bin \) -prune -o -name "main.c" -print
从根目录 / 开始搜索。
忽略 /var/log 和 /usr/bin 目录(及其子目录)。
在其他目录中查找文件名为 main.c 的文件,并打印其路径。
因此,这条命令会在不进入 /var/log 和 /usr/bin 的情况下,查找文件名为 main.c 的文件。
find / -type f -size 0 -exec ls -al {} \;
找到所有大小为0的普通文件,并列出他们的完整路径。
给其他命令传递参数的过滤器命令xargs
linux读取命令有两种方式,命令行参数和标准输入。cat,grep就是这样的命令。
echo 'livey' | cat name1
这个命令组合中cat会输出name1文件的内容,而不是livey字符串,为什么?
此时echo的输出被导入到cat的标准输入,但是cat并不会从标准输入中读取内容,标准输入是一个缓冲区,linux中很多命令都是从命令行中获取参数之后才从标准输入中读取。
echo 'livey' | cat name1 -
这里就会让cat不仅读取name1文件还会读取前面给来的标准输入了。
kill,rm这些程序如果不指定要处理的内容,是不会从标准输入中读取的,所以类似于:
echo '516'| kill 也是无法执行的。
那么实际生产中怎么实现这种思路的命令呢
kill ps -ef| grep 'ddd'这种可以做到。
或者就是使用命令:
for procid in $(ps -aus | grep "some search" | awk '{}print $2'); do kill -9 $procid; done
利用for循环通过ps -aux| grep "some search" | awk '{print $2}'; do kill -9 $procid; done
获取了要kill的所有pid,然后调用kill -9命令。每次处理一个,循环删除。
以下的命令也可以做到
ps -ef | grep 'ddd' |xargs kill
xargs命令可以通过管道接受字符串,并将接收到的字符串通过空格分隔成许多参数。然后传递给后面的命令。
echo '--help' | cat
echo '--help' | xargs cat
第一句输出的是--help,echo的内容被当作标准输入作为cat读取的内容,但是第二句等价于:
cat --help
怎么理解呢?echo的输出通过管道被定向到后面,第一句是直接作为输入处理,第二局则是作为cat的一个命令参数来运行cat命令
例子:
批量重命名文件夹下的文件
touch {1..9}.txt
ls | xargs -t -i mv {} {}.bak
-i参数代表把分割处理传递到{}所在的地方,否则不加该选项就会默认送到命令的尾端。
-t参数表民表示每次执行都会在stderr上打印一遍命令的执行过程,然后才正式执行,类似还有一个-p选项,这一选项运行我们对每一个空格分割的参数都会询问yesorno,
批量删除目录名下为txt后缀的文件
find . -name "*.txt" | xargs -p rm -rf
find . -name "*.txt" | xargs -i -t rm -rf {}
此意为删除找到的所有文件,但是找到的所有文件都是作为一句rm -rf 的参数出现。也就是只有一次yes询问,如果使用-i参数,就会每一个文件都单独作为参数。
-d可以指定分隔符。
echo '11@22@33' |xargs -d '@' echo
输出为:
当不指定xargs后面的命令时,默认调用的是echo命令。
ls | xargs -n 3 -t
-n后面接上一个数字意思是每次传递给后面命令的参数数目。
find 和xargs属于一个rpm包,findutils,之间配合很方便,都是当删除文件名中含有空格的时候,需要特殊注意。
touch "one space.log"
ls
find -name "* *.log"
这里找到的文件会是:
./one space.log
如果交给xargs,会发现它把找到的一个文件以空格分开了成了两节。最后会删除两个不知道存不存在的one文件和space.log文件。
怎么解决?
如果使用find的-print0命令可以让输出的结果用\0来分割,而不是\n,然后使用xargs -0来配对,-0就是特殊的-d选项,也就是指定分隔符为\0。
第二个方法就是不在find上处理,而在xargs上处理,使用-i选项使前面的输出不被分割
find -name "* *.log" | xargs -i rm -rf "{}"
第一个方法更广泛,第二个方法更具通用性。
注意这里大括号两边有双引号来防止中间的空格被解释。
如果不加-i和双引号加括号就会删错文件啦!
文件的连接合并排序去重
join
将两个文件指定列中内容相同的行连接起来。找出两个文件中指定列内容相同的行,加以合并,再输出到stdout设备(标准输出),
join -t
-i
-1
-2
指定分割符
忽略大小写
指定文件第几列整合
指定文件2第几列整合
就像数据库一样,是不是好理解很多,文件1中含有对应列,文件2中也含有对应列,这样两个文件就可以根据这一列互相对应把文件像表格一样组合起来变成一个新的表格。
join -t 't' -1 3 file1.txt -2 3 file2.txt
通过-t指定分隔符,输出内容将file1.txt的第三列和file2.txt的第三列整合。同时相同的字段移到每行最前面。
paste
合并文件的列命令,直接将两个文件相同的行贴在一起。第一行和第一行组合,中间隔一个tab。
paste file1.txt file2.txt
sort
文本排序命令,使用格式为
sort [-t 分隔符] [-kn1,n2] [-nru]
-n意为使用纯数字排序,默认为使用字母顺序进行排序.
-r指的是反向排序
-u指的是只展示重复数据中的一个。
-t指定分隔符
-k以区间排序
cat /etc/passwd | sort |head
cat /etc/passwd | sort -t ':' -k3 -n |head
这里指将数据按照指定的':'分隔符来给我们选的第3列来排序,排序的依据是按照数字排序,最后给head命令输出前十行。
uniq
用于检查和删除文本文件中重复出现的行。一般与sort结合使用。
uniq -c
uniq -d
-c意为在每列判别显示此行重复的次数。
-d意为仅显示重复出现的行。
uniq --count
uniq --repeated
这两句等同前两句。
但是uniq对不相邻的重复行无能为力,这就是使用sort的时候,将这个文件排序之后,重复行就自动相邻了。