Linux的目录结构
| 目录 | 意义 |
|---|---|
| /bin (/usr/bin, /usr/local/bin) | Binary的缩写,这个目录存放着最常使用的命令。 |
| /sbin (/usr/sbin, /usr/local/sbin) | s是super user的意思,这个目录存放着系统管理员使用的系统管理程序。 |
| /lib, /lib64 (/usr/lib, /usr/lib64) | 系统开机所需要的最基本的动态链接库。 |
| /lost+found | 一般是空的,当系统非法关机后,这里就存放了一些文件。 |
| /etc | 所有系统管理所需要的配置文件和子目录,比如redis.conf。 |
| /usr | 用户的很多应用程序和文件存放的目录。 |
| /boot | 存放启动linux时使用的一些核心文件,包括一些连接文件和镜像文件。 |
| /proc | 这是一个虚拟目录,它是系统内存的映射,访问这个目录可以获取系统信息。 |
| /srv | service的缩写,该目录存放一些服务启动之后需要提取的数据。 |
| /sys | linux内核2.6版本引入,该目录下安装了一个新的文件系统。 |
| /tmp | 用来存放临时文件。 |
| /dev | linux下一切皆文件,这部分文件是对硬件的抽象。 |
| /media | linux会自动识别一些设备,比如U盘或者光驱等,当识别成功后,Linux会把识别到的设备挂载到此目录下。 |
| /mnt | Mount的缩写,挂接光驱、USB设备的目录,加载后,会在mnt里多出相应设备的目录。 |
| /opt | 这是给linux主机安装额外软件所准备的目录,比如安装Oracle数据库就可以放在此目录下,默认为空。 |
| /usr/local | 这是另一个给linux主机安装额外软件的目录,一般通过源代码编译安装的都放在这个目录下,比如redis/MySQL。 |
| /var | 这个目录下存放不断扩充的东西,经常需要修改的东西一般都放在此目录下,比如日志文件。 |
远程登陆Linux
首先需要在linux上开启sshd服务,它会监听22端口。ssh是secure shell的简称。
语法:
ssh 用户名@IP
# ssh如果登陆出错可以查看是否存在 ~/.ssh/know_ssh,删除该文件看看能否解决问题
实例:
ssh archer@192.168.33.24
默认情况下,CentOS已经开启了sshd.service,我们可以在终端下输入setup命令(需要root权限),进入Linux的System Service,列表中有前置星号(*)的就是已开启的服务。在这个列表中,按F1可以查看服务介绍,按space可以选中/取消服务,按tab可以退出列表。
注意,如果使用Xshell连接不上远程Linux,考虑关闭CentOS的firewall:
停止firewall
# systemctl stop firewalld.service
禁止firewall开机启动
# systemctl disable firewalld.service
编辑selinux的配置文件
# vi /etc/selinux/config
注释掉下面两行
#SELINUX=enforcing
#SELINUXTYPE=targeted
增加一行
SELINUX=disabled
重启主机
# sync
# shutdown -r now
用户创建
# 创建一个用户名为xiaoming的用户,他家目录为/home/xiaoming
# 同时创建名为xiaoming的用户组,将用户xiaoming加入到用户组xiaoming中
useradd xiaoming
# 创建一个用户名为denny的用户,指定他的家目录为/home/archer
# 同样也会创建名为denny的用户组并将用户denny加入进去
useradd -d /home/archer denny
# 创建用户mayun,他的家目录是/home/mayun,并指定其属于组alibaba
useradd -g alibaba mayun
# 为用户xiaoming创建一个登陆密码
passwd xiaoming
用户删除
# 删除用户xiaoming但保留其家目录
userdel xiaoming
# 删除用户xiaoming及其家目录
userdel -r xiaoming
查询用户信息
# 查询用户archer的信息
id archer
输出 uid=1000(archer),gid=1000(archer),groups=1000(archer)
切换用户
# 使用su命令切换用户,su是switch user的缩写
su root
su - root
su命令与su - 命令的区别:
- su命令:su只是切换了root身份,但Shell环境仍然是普通用户的Shell 而su -连用户和Shell环境一起切换成root身份了。只有切换了Shell环境才不会 现PATH环境变量错误,报command not found的错误。
- su - 命令:su切换成root用户以后,pwd一下,发现工作目录仍然是普通用户的工作目录;而用su -命令切换以后,工作目录变成root的工作目录了。
用户组
# 新增用户组
groupadd alibaba
# 删除用户组
groupdel alibaba
# 修改用户所属的组,新的组必须先存在
# 新建denver组
groupadd denver
# 将melo移交到denver组
usermod -g denver melo
用户和组的相关文件
/etc/passwd
用户的配置文件,记录着用户信息。
# /etc/passwd中的一行对应如下
archer:x:1000:1000:Denny Archer:/home/archer:/bin/bash
用户名:密码标志:uid:gid:注释性描述:家目录:登陆的Shell
- Linux内部是通过uid来区别用户的,用户名只是为了方便系统使用者, 用户名和uid的对应关系就在/etc/passwd文件中定义。
- Linux用户的登陆密码存储在/etc/shadow文件中,密码标志只有一个"x"代表 用户是拥有密码的,如果把"x"删掉,系统就会认为此用户没有密码,进而只通过 输入用户名就可以登陆系统。
- uid为0表示root用户,如果把某个用户的uid改为0,那么这个用户就会变成root 用户。在Linux中,1~499是系统保留的,用来运行系统服务。
- 登陆的shell可以理解为用户登陆后所拥有的权限,即这个用户能干什么。比如 如果是标准shell(/bin/bash),那这个用户能做普通用户能做的所有事情,如果改成 /sbin/nologin,那这个用户就不能登陆了,因为/sbin/nologin是禁止登陆的shell。
/etc/shadow
口令配置文件
# /etc/shadow中的一行对应如下
archer:$6$qDAYQCfVWxUkc10r$obR4MmplCe2kxoHYHUp.gimZAOihAogC0::0:99999:7:::
用户名:加密后的密码:密码最后修改日期:密码修改间隔:密码有效期:密码修改到期前的警告天数:密码过期后的宽限天数:账号失效时间:保留,暂未使用
- 如果手工修改加密后的密码,会导致算不出原密码,进而导致该用户无法登录, 基于此,我们可以在密码前添加 ! 或 * 来使密码失效从而限制用户登陆。
- 如果加密的密码上是 "!!" 或者 "*", 代表没有密码不能登陆,如果创建 新用户时没有设置密码,那么也是"!!",因而也不能登陆。
- 密码修改间隔如果是0表示可以随便修改,如果是10表示10天内不能再次修改, 这个10天是相对于密码最后修改日期而言的。
- 密码有效期默认是99999,可以理解为永久有效,如果是90,就是说90天之后必须 再次修改密码,否则不能登陆,这个90天也是相对于密码最后修改日期而言的。
- 密码修改到期前的警告天数要和密码有效期相比,就是密码到期前需提前几天修 改。默认值是7,也就是说从密码到期前的7天开始,每次登录系统都会警告该用户 修改密码。
- 密码过期后的宽限天数也就是说密码过期后,用户如果还是没有修改密码,那么 在宽限天数内用户还是可以登录系统的;如果过了宽限天数,那么用户就无法再使用 该密码登录了。天数如果是10,则代表密码过期10天后失效;如果是0,则代表密码 过期后立即失效;如果是 -1,则代表密码永远不会失效。
- 账号失效时间,这里也要是时间戳(天数,相对于1970.1.1),如果账号过期了, 即使密码没有过期,账号也不能使用。
/etc/group
组配置文件
# /etc/group中的一行对应如下
archer:x:1000:archer
用户名:密码标志:gid:组内成员列表
指令运行级别
Linux默认提供7个运行级别(runlevel):
- 0:系统停机状态,系统默认运行级别不能设为0,否则不能正常启动
- 1:单用户工作状态,root权限,用于系统维护,禁止远程登陆
- 2:多用户状态(没有NFS)
- 3:完全的多用户状态(有NFS),登陆后进入控制台命令行模式
- 4:系统未使用,保留
- 5:X11控制台,登陆后进入图形GUI模式
- 6:系统正常关闭并重启,默认运行级别不能设为6,否则不能正常启动
运行级别的配置文件是/etc/inittab。CentOS 7已经不使用运行级别了,而是改用 target,默认提供两种target:
- multi-user.target: 类似于runlevel 3
- graphical.target: 类似于runlevel 5
# 查询默认的target
systemctl get-default
# 设置默认的target
systemctl set-default TARGET.target
mkdir
描述:
创建文件夹
参数:
-p/--parents参数用来创建多级目录
实例:
# 在当前目录下创建war3文件夹
mkdir war3
# 在当前目录下创建games文件夹,再在games下创建war3文件夹
mkdir -p games/war3
rmdir
描述:
删除*空*文件夹,如果文件夹非空,则不能删除。
参数:
-p:删除多级目录
实例:
# 删除/home/archer下的dog目录
rmdir /home/archer/dog
# 删除当前目录下的games文件夹和games下的war3文件夹
rmdir -p games/war3
rm
描述:
删除文件或文件夹,默认不删除文件夹,可以通过参数来实现。
使用:
rm [option]... file/dir... # ...表示多个
参数:
-f:强制删除,不管有没有文件。
-r:递归删除,可以删除文件夹及文件夹里面的内容
# 实例:
# 删除当前文件夹下的log.txt
rm log.txt
# 如果文件名以-开头,比如-log.txt
rm ./-log.txt
# 删除文件夹games下的所有内容
rm -rf games
cp
描述:
拷贝文件或文件夹。
使用:
cp src dest # 将src拷贝到dest,dest也是普通文件名而不是文件夹
cp src... dir # 将多个文件拷贝到指定文件夹
参数:
-r:递归复制整个文件夹
-a: 复制文件和目录,以及它们的属性,包括所有权和权限。通常,复本具有用户所操作文件的默认属性。
-u/--update: 当把文件从一个目录复制到另一个目录时,仅复制目标目录中不存在的文件,
或者是文件内容新于目标目录中已经存在的文件。
实例:
# 将当前文件夹下的log.txt复制到logs下的logback.txt
cp log.txt logs/logback.txt
# 将1.txt 2.txt 3.txt复制到logs文件夹
cp 1.txt 2.txt 3.txt logs
# 将logs文件夹复制到logback文件夹
cp -r logs logback
# 将logs目录下的所有文件都复制到logback目录下
cp logs/* logback
# 仅向logback目录中复制其不存在的或已经存在但是更新的文件
cp -u logs/* logback
mv
描述:
移动或重命名文件
参数:
-u/--update: 当把文件从一个目录移动另一个目录时,只是移动不存在的文件,
或者文件内容新于目标目录相对应文件的内容。
使用:
mv src dest # 重命名src为dest
mv src... dir # 将多个文件移动到dir
实例:
# 将当前文件夹下的logbak.txt重命名为log.txt
mv logback.txt log.txt
# 将1.txt 2.txt移动到logs文件夹
mv 1.txt 2.txt logs
cat
描述:
查看文件内容,以只读的方式打开,不能修改
参数:
-n:输出行号
-A: 输出不可见字符
实例:
# 查看spring.log的内容并打印在标准输出上
cat -n spring.log
# 由于cat指令会把文件内容一次性输出到控制台上,如果需要分页显示,
# 可以接上more或less
cat -n ~/.bash_history | less
less
分屏查看文件内容。less指令在显示文件内容时,并不是一次将整个文件都加载之后才显示,而是按需加载,对于大型文件来说效率较高。常用快捷键有:
- space: 向下翻页
- PgUp: 向上翻页
- PgDn:向下翻页
- /keyword:往下搜索关键字,n下一个,N上一个
- ?keyword:往上搜索关键字,n上一个,N下一个
>指令和>>指令
>: 输出重定向
>>: 追加
# 将ls输出的内容覆盖写入a.txt
ls -l > a.txt
# 将ls输出的内容追加到a.txt末尾
ls -l >> a.txt
# 将/etc/profile的内容覆盖写入/home/archer/Documents
# 下的profile.txt
cat /etc/profile > /home/archer/Documents/profile.txt
小技巧
当我们使用“>”重定向符来重定向输出结果时,目标文件总是从开头被重写。因此,如果我们需要删除一个文件内容(或者创建一个新的空文件),可以使用这样的技巧:
# 简单地使用重定向符,没有命令在它之前,这会删除一个已存在文件的内容或是创建一个新的空文件
[archer@localhost ~]$ > output.txt
重定向标准错误
重定向标准错误缺乏专用的重定向操作符。重定向标准错误,必须参考它的文件描述符。在shell中,标准输入,标准输出和标准错误的文件描述符分别是0,1,2,因此可以这样重定向标准错误:
# 标准错误的文件描述符(2)紧贴在重定向符(>)之前
ls -l /bin/usr 2> ls-output.txt # /bin/usr并不存在,因此会产生一条出错信息
有时候需要捕捉一个命令的所有输出到同一个文件,因此需要同时重定向标准输出和标准错误,可以这样执行联合重定向:
# 使用单单一个表示法 &> 来重定向标准输出和错误到文件 lsoutput.txt
ls -l /usr/bin &> ls-output.txt
如果不想要一个命令的输出结果,可以将其重定向到一个特殊的文件——"/dev/null"。这个文件可以接收输入,但对输入不做任何处理:
# 丢弃ls的错误信息
ls -l /bin/usr 2> /dev/null
重定向标准输入
# 使用“<”重定向操作符,把标准输入源从键盘改到文件log.txt
cat < log.txt
虽然执行结果和将log.txt作为参数传递给cat是一样的,但是这种方式是将log.txt作为标准输入源。
head
描述:
显示文件的开头部分,默认情况下显示前10行。
参数:
-n: 显示前多少行
实例:
# 显示/etc/profile的前5行
head -n 5 /etc/profile
tail
描述:
显示文件的结尾部分,默认情况下显示最后10行。
参数:
-n: 显示最后多少行
-f: 随着文件的增长输出附加的数据,通过监听文件描述符
-F: 随着文件的增长输出附加的数据,通过监听文件名
实例:
# 显示/etc/profile的最后5行
tail -n 5 /etc/profile
# 输出log.txt的最后10行,并跟踪其更新
tail -f log.txt
find
描述:
递归的遍历指定文件夹,将满足要求的文件或文件夹显示在终端上。
用法:
find [搜索路径] [参数]
参数:
-name: 按名称搜索
-user: 按所属用户搜索
-size: 按大小搜索
+10M 大于10M
10M 等于10M
-10M 小于10M
实例:
# 搜索整个文件系统中大于20M的文件
find / -size +20M
# 在当前文件夹下搜索log.txt
find . -name log.txt
# 在/home/archer文件夹下搜索所有的txt文件
find /home/archer *.txt
# 搜索所有属于archer的文件
find / -user archer
zip/unzip
描述:
zip用于压缩文件或文件夹
用法:
zip [OPTION...] xxx.zip [FILE/DIR...]
参数:
-r: 递归压缩,即压缩目录
实例:
# 压缩log.txt
zip log.zip log.txt
# 压缩a.log和b.log到logs.zip
zip logs.zip a.log b.log
# 压缩logs文件夹
zip -r logs.zip logs
描述:
unzip用于解压缩
用法:
unzip [参数] xxx.zip
参数:
-d: 解压缩到指定文件夹
实例:
# 解压log.zip
unzip log.zip
# 解压到logs文件夹
unzip -d logs log.zip
tar
描述:
打包指令
用法:
tar [OPTION...] [FILE...]
参数:
-c: 产生.tar文件
-v: 显示详细信息
-f:指定压缩后的文件名
-z: 打包的同时进行压缩
-x: 解包.tar文件
-C: 指定文件夹
实例:
# 将a.log和b.log打包进logs.tar
tar -cf logs.tar a.log b.log
# 将a.log和b.log打包进logs.tar并使用gzip压缩
tar -zcf logs.tar.gz a.log b.log
# 对/home/archer目录下的所有文件进行打包并压缩
tar -zcvf archer.tar.gz /home/archer
# 解包logs.tar.gz到当前文件夹
tar -zxvf logs.tar.gz
# 解包logs.tar.gz到logs文件夹(必须存在)
tar -zxvf logs.tar.gz -C logs
chown
描述:
修改文件所有者
用法:
chown [OPTION...] [OWNER][:GROUP] FILE...
参数:
-R:递归修改,用于文件夹
-h: 影响符号连接
实例:
# 将logs文件夹由root所有变为archer所有
# 仅改变文件夹所有权,文件夹里的东西不受影响
chown archer logs
# 将logs文件夹及其下的所有东西变为archer所属
chown -hR archer logs
# 将a.log的所有者和所属组均改为archer
chown archer:archer a.log
chgrp
描述:
修改文件所属组
用法:
chgrp [OPTION...] [GROUP] FILE...
参数:
-R:递归修改,用于文件夹
-h: 影响符号连接
实例:
# 将a.log的所属组改为archer
chgrp archer a.log
# 将logs文件夹由root组变为archer组
# 仅改变文件夹所属组,文件夹里的东西不受影响
chgrp archer logs
# 将logs文件夹及其下的所有东西变为archer组
chgrp -hR archer logs
文件和文件夹rwx权限的区别
-
文件:
- r: 可以读取和查看文件内容
- w:可修改,但不代表可删除(可删除的前提是对该文件所在文件夹有w权限)。
- x: 可执行
-
文件夹:
- r: 可查看文件夹内的内容,比如可以使用ls命令
- w:可在此文件夹内执行创建和删除操作,也可以重命名此文件夹
- x:能否进入此目录(cd命令能否执行)
tree
描述:
查看目录树
如果没有安装,先执行yum install tree进行安装。
crontab任务调度
描述:
crontab可以进行定时任务的配置,可以用于MySql备份,日志的整理等。
参数:
-e: 编辑当前定时任务
-l:打印当前定时任务
-r:删除当前定时任务
实例:
crontab -e
* * * * * [user-name] commands
星号从左到右:
1. 分钟,0~59
2. 小时,0~23
3. 一个月的某一天,1~31
3. 一年的某一月,1~12
5. 星期几,0~7,其中0和7都表示星期天
星号(*)代表任何时间,比如上面例子中的第一个*表示一个小时的每分钟都执行。
逗号(,)代表不连续的时间,比如 0 8,12,23 * * * 表示每天的8点0分,12点0分,
23点0分各执行一次。
中横线(-)代表连续的时间,比如 0 5 * * 1-6 表示每周周一到周六的早上5点0分
执行一次。
*/n代表每隔多久执行一次,比如*/5就表示每隔五分钟执行一次。
# 重启调度任务
service crond restart
# 每分钟都追加一次日期到mydate
* * * * * date >> /tmp/mydate
# crontab调用脚本
1. 编写一个脚本my.sh,假设放在/home/archer下,注意脚本里只有命令,定时信息
通过crontab -e 编辑
2. 确保my.sh有可执行的权限
3. 命令行输入crontab -e
4. 在进入的编辑栏里补上定时信息,并跟上脚本的路径,
比如 */5 * * * * /home/archer/my.sh,表示每5分钟调用一次my.sh脚本
df
描述:
查询系统磁盘的使用情况
参数:
-h: human readable
实例:
df -h
du
描述:
查询指定目录的磁盘占用情况
使用:
du [OPTION...] DIR...
参数:
-s: 指定目录占用大小汇总
-h: human readable
-a: 含文件
-c: 列出明细的同时,增加汇总值
-d/--max-depth=n:子目录深度
实例:
# 查询/opt目录磁盘占用情况,深度为1
du -ach --max-depth=1 /opt
wc
描述:
统计指令,可以统计一个文件中的newline,character,words,或是文件的byte
参数:
-m:统计character
-l:统计newline
-w:统计word
-c:统计bytes
实例:
# 统计/home目录下的文件个数
ls -l | grep "^-" | wc -l # ls -l将分行显示所有的文件和文件夹,再通过grep选出文件,最后统计一下行数就是文件数了
给Linux主机指定固定的ip
修改/etc/sysconfig/network-scripts/文件夹下的网卡映射文件(ifconfig可以查看网卡映射文件的名称)。
几个重要的地方:
ONBOOT=yes # 启动系统时开启
BOOTPROTO=static # dhcp static 由dhcp改为static
IPADDR=192.168.33.24 # 指定ip地址
GATEWAY=192.168.33.2 # route -n 第一行就是网关
DNS1=8.8.8.8 # 固定值
修改完成以后重启网络服务:
service network restart
ps
描述:
显示进程信息
参数:
-e: 显示所有进程
-f: 全格式
实例:
# 用标准的格式显示进程
ps -ef
格式解释:
kill 和 killall
描述:
用来终止进程(给内核发送signal)
使用:
kill [OPTION...] pid # 通过进程id终止进程
killall pname # 通过进程名终止进程,支持通配符
参数:
-9:立即终止
实例:
# 踢掉远程登陆的非法用户
# 先使用ps -ef | grep sshd 列举出所有远程登陆的进程
# 在输出中找到非法登陆的进程id,比如1024
kill -9 1024
# 终止所有IDEA
killall idea
pstree
描述:
查看进程树
参数:
-p: 显示进程pid
-u:显示进程所属用户
service
描述:
服务管理
服务(service)的本质是进程,但是是运行在后台的,通常都会监听某个端口,等待其它程序的请求。
使用:
service 服务名 start/stop/restart/reload/status
systemctl用在CentOS 7以后 systemctl start/stop/restart/reload/status xxx.service
top
描述:
动态监控进程。top和ps很相似,它们都用来显示正在执行的进程。top和ps的区别在于top可以更新正在运行的进程信息。
参数:
-d:指定top命令每隔几秒更新,默认3秒。
-i:不显示任何僵死或闲置进程
-p:通过指定进程id只监控这一个进程的信息
交互指令:
P: 以cpu使用率排序,默认
M:以内存使用率排序
N:以pid排序
u: 只查询属于某个用户的进程
k: 终止某一进程
q:退出top
top 显示结果由两部分组成: 最上面是系统概要,下面是进程列表,默认的使用率排序。其中系统概要包含许多有用信息。下表是对系统概要的说明:
| 行号 | 字段 | 意义 |
|---|---|---|
| 1 | top | 程序名 |
| - | 14:40:16 | 当前时间 |
| - | up 21:42 | 这是正常运行时间。它是计算机从上次启动到现在所运行的时间。在这个例子里,系统已经运行了21小时42分 |
| - | 1 user | 当前只有一个用户登陆系统 |
| - | load average | 加载平均值是指,等待运行的进程数目,也就是说, 处于运行状态的进程个数,这些进程共享 CPU。展示了三个数值,每个数值对应不同的时间周期。第一个 是最后 60 秒的平均值,下一个是前 5 分钟的平均值, 最后一 个是前 15 分钟的平均值。若平均值低于 1.0, 则指示计算机工作不忙碌。 |
| 2 | Tasks | 总结了进程数目和各种进程状态 |
| 3 | %Cpu(s) | 这一行描述了 CPU 正在执行的进程的特性。 |
| - | 0.0 us | 0.0%的CPU用于用户进程。 这个表示内核本身之外的进程。 |
| - | 0.1 sy | 0.1% 的 CPU 时间被用于系统(内核)进程。 |
| - | 0.0 ni | 0.0% 的 CPU 时间被用于”nice”(低优先级)进程。 |
| - | 99.9 id | 99.9% 的 CPU 时间是空闲的。 |
| - | 0.0 wa | 0.0% 的 CPU 时间来等待 I/O。 |
| - | 0.0 hi | 0.0% 的 CPU 时间来等待硬件中断。 |
| - | 0.0 si | 0.0% 的 CPU 时间来等待软件中断。 |
| 4 | Mem | 展示物理内存的使用情况。 |
| 5 | Swap | 展示交换分区(虚拟内存)的使用情况。 |
netstat
描述:
netstat 命令是Linux用于显示各种网络相关信息,是一个监控TCP/IP网络的非常有用的工具,
如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,
多播成员 (Multicast Memberships) 等等。
参数:
-a或--all:显示所有选项,默认不显示LISTEN相关
-t或--tcp:仅显示tcp相关选项
-u或--udp:仅显示udp相关选项
-n或--numeric:直接使用ip地址,而不通过域名服务器(拒绝显示别名,能显示数字的全部转化成数字)
-l或--listening:仅列出有在 Listen (监听) 的服務状态
-p或--programs:显示建立相关链接的程序名
-r或--route:显示路由信息,路由表
-e或--extend:显示扩展信息,例如uid等
-s或--statistice:显示网络工作信息统计表(按各个协议进行统计)
-c或--continuous:每隔一个固定时间,执行该netstat命令。
提示:LISTEN和LISTENING的状态只有用-a或者-l才能看到
free
描述:
显示系统中的内存信息(包括已使用的和空闲的)
参数:
-h: human readable
-t:为每一列增加一个汇总值total
实例:
free -ht
ls
描述:
列举目录中的内容
参数:
-t: 按最后修改时间排序
-S:按文件大小排序
-r/--reverse:按相反的顺序输出
-R/--recursive:列举出子目录中的内容
-d:输出目录本身信息而不是目录中的内容,一般配合-l选项
-h:human readable
-a:显示隐藏文件
-l:按长格式输出
实例:
# 输出当前目录的详细信息
ls -ld
# 输出当前目录的所有内容,最近修改的在最前面
ls -lt
# 输出当前目录的所有内容,最近修改的在最后面
ls -ltr
file
描述:
确定文件的格式。Linux系统并不通过文件后缀名来区分其类型,诸如pet.jpg的文件并不一定真的是jpeg格式的图片。
参数:
-i:输出文件的mine type而不是普通描述信息
通配符和字符类
接受文件名作为参数的任何命令,都可以使用通配符。
通配符:
* 匹配任意多个字符(包括0个或1个)
? 匹配任意一个字符(不包含0个)
[characters] 匹配任意一个属于字符集中的字符
[!characters] 匹配任意一个不属于字符集中的字符
[[:class:]] 匹配任意一个属于指定字符类中的字符
字符类:
[:alnum:] 匹配任意一个字母或数字
[:alpha:] 匹配任意一个字母
[:digit:] 匹配任意一个数字
[:lower:] 匹配任意一个小写字母
[:upper:] 匹配任意一个大写字母
实例:
* 所有文件
g* 任何以g开头的文件
b*.txt 任何以b开头的txt文件
data??? 以data开头,后跟任意三个字符的文件
[abc]* 任何以a,或b,或c开头的文件
backup.[0-9][0-9][0-9] 以backup.开头,后跟任意三个数字的文件 # [0-9]表示任意一个数字
[[:upper:]]* 任何以大写字母开头的文件
[![:digit:]]* 任何不以数字开头的文件
*[[:lower:]123] 任何结尾是一个小写字母或数字1,2,3的文件,比如AAAAa, BBBB1, CCCC3
花括号展开
我们可以从一个包含花括号的模式中创建多个文本字符串。花括号表达式本身可能包含一个由逗号分开的字符串列表,或者一系列整数,或者单个的字符串。这种模式不能嵌入空白字符。
# 包含由逗号分开的字符串列表
echo prefix-{A,B,C}-suffix # prefix-A-suffix prefix-B-suffix prefix-C-suffix
# 包含一系列整数
echo number-{1..3} # number-1 number-2 number-3
# 包含一系列倒数的字符
echo {Z..P} # Z Y X W V U T S R Q P
# 可以嵌套
echo a{A{1,2},B{3,4}}b # aA1b aA2b aB3b aB4b
# 创建一系列目录
mkdir {2020..2025}-{1..12} # 创建从2020-1到2025-12的一系列文件夹
引号
如果把文本放在双引号中,shell使用的特殊字符,除了$,(反斜杠),和`(倒引号)之外,则失去它们的特殊含义,被当作普通字符来看待。这意味着单词分割,路径名展开,波浪线展开,和花括号展开都被禁止,然而参数展开,算术展开,和命令替换仍然执行。 **
# 参数展开
echo "$PATH"
# 算数展开
echo "$[5+3]"
# 命令替换
echo "$(ls -l)"
# 双引号用来处理带空格的文件名,避免文件名被shell解释成两个独立单词
echo "hello world.txt"
如果需要禁止所有的展开,那就使用单引号。
# 原样输出 不做任何展开
echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER'
键盘操作
移动光标
- ctrl+a:移动光标到行首
- ctrl+e:移动光标到行尾
- ctrl+f:光标向前移动一个字符,和右箭头作用一样
- ctrl+b:光标向后移动一个字符,和左箭头作用一样
- alt+f:光标向前移动一个字,以单词为单位
- alt+b:光标向后移动一个字,以单词为单位
修改文本 ctrl+d:删除光标处的字符
sort
描述:
针对文本文件的内容,以行为单位来排序。
sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。
参数:
-b:忽略每行开始的空格字符,从第一个可见字符开始
-n:按数值大小排序,默认以字符进行排序,因此可能造成10比2小的情况,因为10的第一个字符1比2小
-r:反向排序
-u:去除重复行
-f:忽略大小写
-t<分隔字符>:指定排序时所用的栏位分隔字符
-o:用重定向无法将sort的输出写到原文件中,比如sort log.txt > log.txt不会写入排序后的结果反而会清空log.txt中的内容,
-o选项解决了这个问题:sort log.txt -o log.txt
实例:
1. 假定文件fruits.txt内容为:
banana:30:5.5
apple:10:2.5
pear:30:2.3
orange:20:3.4
这个文件有三列,列与列之间用冒号隔开了,第一列表示水果类型,第二列表示水果数量,第三列表示水果价格。那么我想以水果数量来排序,也就是以第二列来排序,如何利用sort实现?
sort -n -t: -k 2 fruits.txt # -n是必要的,因为要按数值进行排序
2. 可以看到banana和pear的数量是一样的,按数量排序时如何决定banana和pear的先后顺序呢?答案是可以指定排序的优先级,也就是使用多个-k选项:
# 先按照第二列排序,第二列相同的时候再按照第三列排序
sort -n -t: -k 2 -k 3 fruits.txt
3. -k选项还可以加上modifier
sort -t: -k 2n -k 3nr fruits.txt # 先按照第二列的数值排序,相同的情况下按照第三列的数值反向排序
进程
当系统启动的时候,内核先把一些它自己的程序初始化为进程,然后运行一个叫做 init 的程序。init,依次地,再运行一系列的称为 init 脚本的 shell 脚本(位于/etc),它们可以启动所有的系统服务。其中许多系统服务以守护(daemon)程序的形式实现,守护程序仅在后台运行,没有任何用户接口。这样,即使我们没有登录系统,至少系统也在忙于执行一些例行事务。
内核维护每个进程的信息,以此来保持事情有序。例如,系统分配给每个进程一个数字, 这个数字叫做进程 ID 或 PID。PID 号按升序分配,init 进程的 PID 总是 1。内核也对分配给 每个进程的内存进行跟踪。像文件一样,进程也有所有者和用户 ID,有效用户 ID,等等。
软件包管理
软件包管理系统通常由两种工具类型组成:底层工具用来处理这些任务,比方说安装 删除软件包文件,和上层工具,完成元数据搜索和依赖解析。
| 发行版 | 底层工具 | 上层工具 |
|---|---|---|
| Debian-Style | dpkg | apt-get |
| CentOS | rpm | yum |
yum和apt
| 上层工具 | 搜索 | 安装 | 卸载 | 更新系统中的软件包 |
|---|---|---|---|---|
| yum | yum search keyword | yum install package_name | yum erase package_name | yum update |
| apt | apt-get update; apt-cache search keyword | apt-get update; apt-get install package_name | apt-get remove package_name | apt-get update; apt-get upgrade |
dpkg和rpm
| 下层工具 | 安装 | 升级 | 显示安装到系统的所有软件包 | 查询是否安装了指定软件包 | 查找安装了某个文件的软件包 |
|---|---|---|---|---|---|
| dpkg | dpkg --install package_file | dpkg --install package_file | dpkg --list | dpkg --status package_name | dpkg --search file_name |
| rpm | rpm -i package_file | rpm -U package_file | rpm -qa | rpm -q package_name | rpm -qf file_name |
# 查询哪个软件包安装了vim
rpm -qf /usr/bin/vim
find
find 程序能基于各种各样的属性,搜索一个给定目录(以及它的子目录),来查找文件。 find 命令的美丽所在就是它能够被用来识别符合特定标准的文件。它通过(有点奇怪)应用选项,测试条件,和操作来完成搜索。我们先看一下测试条件。
# 找出家目录下的所有目录并统计
find ~ -type d | wc -l
# 找出家目录下的所有文件并统计
find ~ -type f | wc -
# 找出家目录下所有大于1M的jpg文件
find ~ -type f -name "*.jpg" -size +1M
find 命令支持大量不同的测试条件。请注意,在需要数值参数的情况下,可以应用“+”和 “-” 符号表示法:
| 测试条件 | 描述 |
|---|---|
| -empty | 匹配空文件和目录。 |
| -group name | 匹配的文件和目录属于一个组。组可以用组名或组 ID 来表示。 |
| -name pattern | 用指定的通配符模式匹配的文件和目录。 |
| -iname pattern | 就像 -name 测试条件,但是不区分大小写。 |
| -mmin n | 匹配的文件或目录的内容被修改于 n 分钟之前。 |
| -mtime n | 匹配的文件或目录的内容被修改于 n * 24小时之前(也就是n天之前)。 |
| -newer file | 匹配的文件和目录的内容早于指定的文件。当编写 shell 脚本,做文件备份时,非常有帮助。每次你制作一个备份,更新文件(比如说日志),然后使用 find 命令来决定自从上次更新,哪一个文件已经更改了。 |
| -nouser | 匹配的文件和目录不属于一个有效用户。这可以用来查找属于删除帐户的文件或监测攻击行为。 |
| -nogroup | 匹配的文件和目录不属于一个有效的组。 |
| -perm mode | 匹配的文件和目录的权限已经设置为指定的 mode。mode 可以用八进制或符号表示法。 |
| -size n | 匹配的文件大小为 n。 |
| -type c | 匹配的文件类型是 c。 |
| -user name | 匹配的文件或目录属于某个用户。这个用户可以通过用户名或用户 ID 来表示。 |
grep
grep程序会在文本文件中查找一个指定的正则表达式,并把匹配行输出到标准输出。
# grep的使用格式
grep [options] regex [file...]
其常用的参数如下:
| 参数 | 描述 |
|---|---|
| -i | 忽略大小写。也可用 --ignore-case 来 指定。 |
| -v | 不匹配。通常,grep 程序会打印包含匹配项的文本行。这个选项导致 grep 程序只会不包含匹配项的文本行。也可用 --invert-match 来指定。 |
| -c | 打印匹配的数量(或者是不匹配的数目,若指定了 -v 选 项),而不是文本行本身。也可用 --count 选项来指定。 |
| -l | 打印包含匹配项的文件名,而不是文本行本身。也可用 --files-with-matches 选项来指定。 |
| -L | 相似于 -l 选项,但是只是打印不包含匹配项的文件名。也可用 --files-without-match 来指定。 |
| -n | 在每个匹配行之前打印出其位于文件中的相应行号。也可用 --line-number 选项来指定。 |
| -h | 应用于多文件搜索,不输出文件名。也可用 --no-filename 选项来指定。 |
准备数据:
ls /bin > dirlist-bin.txt
ls /sbin > dirlist-sbin.txt
# 在dirlist-*.txt中搜索字符串bzip,打印匹配的那一行及其所属文件
grep bzip dirlist-*.txt
# 输出包含匹配项的文件列表而不是文件本身
grep -l bzip dirlist-*.txt
Shell入门
shell脚本均以 #!/bin/bash (shebang)开头,注意给予其可执行权限。
shell脚本中的注释方式:
# 单行注释
:<<!
多行注释
多行注释
多行注释
!
如何执行shell脚本
有两种方式可以执行shell脚本:
- 赋予shell脚本可执行权限,通过输入其文件名执行
- 通过sh命令来执行,格式为 sh 脚本名
shell中的变量
在bash中,每一个变量的值都是字符串。 无论你给变量赋值时有没有使用引号,值都会以字符串的形式存储。Linux Shell中的变量分为系统变量和用户自定义变量,系统变量比如PATH,HOME,USER等。
shell变量的定义
自定义变量:
语法:
变量名=值
实例:
num=100
删除自定义变量:
语法:
unset 变量名
实例:
unset num
定义静态变量:
语法:
readonly 变量名=值
实例:
readonly okay=200
注意:静态变量只能读取,不能unset
将命令的返回值赋予变量:
语法:
1. 变量名=`要执行的命令`
2. 变量名=$(要执行的命令)
实例:
A=`ls -l` # 将ls -l的返回值赋给变量A
A=$(ls -l) # 等价于A=`ls -l`
定义变量的时候有几个点需要注意一下:
- 不能以数字开头,且一般采用大写
- 等号两端不能有空格,num=10可以,num = 10不行
设置环境变量
- export 变量名:将shell变量导出为环境变量
- source 配置文件名:让修改后的配置信息立即生效
位置参数变量
当执行一个shell脚本时,如果希望获取命令行参数,就可以使用位置参数变量。比如在命令行执行 ./my.sh 100 200,可以使用位置参数变量来获取100和200这两个命令行参数。
$n:n为数字,其中$0为命令本身,$1-$9表示第一到第九个参数,十以上的参数需要使用大括号,比如${10}表示第十个参数
$*:表示命令行中的所有参数,$*把所有的参数看成一个整体
$@: 也表示命令行中的所有参数,不过$@把每个参数区分对待
$#: 表示命令行中参数的个数
预定义变量
预定义变量是shell设计者事先定义好的变量,可以直接在脚本中使用.
?: 当前进程id
$!: 后台运行的最后一个进程的id
$?: 最后一次执行的命令的返回值,0表示成功,非0表示失败
运算符
1. $((运算式))或$[运算式]
2. expr m + n, 注意expr运算符间要有空格(+, -, \*, /, %分别对应加减乘除和取模运算)
计算(2 + 3) * 4
使用$[]:
$[(2+3)*4]
使用expr:
SUM=$(expr 2 + 3) # expr是一个表达式,需要使用$()来引用其结果
echo $(expr $SUM \* 4)
条件判断
基本语法:
[ condition ] # 注意condition前后要有空格
非空返回true,可使用 $? 验证,0为true,>1为false
实例:
[ archer ] # 返回true
[] # 返回false
常用判断条件:
0. = # 字符串比较
1. 两个整数的比较
-lt # 小于
-le # 小于等于
-gt # 大于
-ge # 大于等于
-eq # 等于
-ne # 不等于
2. 按照文件权限进行判断
-r # 有读的权限
-w # 有写的权限
-x # 有执行的权限
3. 按照文件类型进行判断
-f # 文件存在且是普通文件
-e # 文件存在
-d # 文件存在且是目录
实例:
# "ok"是否等于"ok"
[ "ok" = "ok" ]
# 23是否大于22
[ 23 -gt 22 ]
# /root/install.log是否存在
[ -e /root/install.log ]
流程控制
if:
语法:
第一种形式:
if [ condition ];then
# code goes here
fi
第二种形式:
if [ condition ]
then
# code goes here
elif [ condition ]
then
# code goes here
fi
实例:
NUM=101
if [ $NUM -eq 101 ];then
echo "NUM = 101"
fi
if [ $NUM -gt 100 ]
then
echo "NUM > 100"
else
echo "NUM <= 100"
fi
if [ $NUM -gt 200 ]
then
echo "NUM > 200"
elif [ $NUM -gt 150 ]
then
echo "NUM > 150"
elif [ $NUM -gt 100 ]
then
echo "NUM > 100"
else
echo "NUM <= 100"
fi
case:
语法:
case $变量名 in
"值1")
# code goes here
;;
"值2")
# code goes here
;;
...... # 其他分支
*)
# default分支
;;
esac # case的反转
实例:
case $1 in
"1")
echo "星期一"
;;
"2")
echo "星期二"
;;
"3")
echo "星期三"
;;
"4")
echo "星期四"
;;
"5")
echo "星期五"
;;
*)
echo "未知工作日"
;;
esac # 不要忘了结束case
for:
语法:
第一种形式:
for 变量 in 值1, 值2, 值3 ...
do
# code goes here
done
第二种形式:
for((初始值;循环控制条件;变量变量))
do
# code goes here
done
实例:
# 遍历命令行参数
# $*将所有命令行参数视作一个整体,如果使用$*,这里只会有一个输出
for i in $@ # 这一句的意思是遍历 $@并将值赋值给i
do
echo "i = $i"
done
# 计算0-49的和
sum=0
for((i=0;i<50;i++))
do
sum=$[$sum+$i]
done
echo "sum = $sum"
while:
形式:
while [ condition ]
do
# code goes here
done
实例:
# 从命令行输入一个数n,统计1+2+...+n的值
i=1
sum=0
while [ $i -le $1 ]
do
sum=$[$sum+$i]
i=$[$i+1]
done
echo $sum
自定义函数
语法:
[ function ] funcname[()] {
# codes goes here
[return int;]
}
# 注意shell的函数不需要写形参,中括号里的内容是可选的
实例:
# 计算两个参数的和
#!/bin/bash
function sum() {
SUM=$[$n1+$n2] # shell函数没有形参,$n1 $n2是调用时传递的实参
echo $SUM
}
# read用来读取命令行输入,它会阻塞当前进程直至输入完成
read -p "请输入一个整数\n" n1 # 定义n1
read -p "请再输入一个整数\n" n2 # 定义n2
sum $n1 $n2 # 调用自定义的sum函数,传递$n1 $n2两个参数,这样$n1 $n2就能在函数体使用了
综合案例
编写shell脚本定时维护数据库,要求:
- 每天凌晨2:10备份数据库insoDB到data/backup/db
- 备份开始和结束需要给出提示信息
- 备份的文件要求以备份时间命名,并打包成tar.gz格式,比如2020-03-12_021545.tar.gz
- 在备份的同时,检查是否有十天前的文件,有就将其删除
endgame.sh:
#!/bin/bash
# 记录备份时间
DATETIME=$(date +%Y-%m-%d_%H%M%S)
# 定义备份文件夹
BACKUP_DIR=/data/backup/db
# 创建文件夹,如果不存在 shell的取反也是使用 !
if [ ! -d $BACKUP_DIR ];then
mkdir -p $BACKUP_DIR
fi
# 创建临时文件夹来存储数据库备份文件
cd $BACKUP_DIR
mkdir $DATETIME
echo "========备份开始=========="
# MySQL主机地址
HOST=localhost
# MySQL用户名
DB_USER=root
# MySQL密码
DB_PWD=123
# 要备份的数据库
DATABASE=insoDB
# 执行MySQL备份指令
mysqldump -u$DB_USER -p$DB_PWD --host=$HOST $DATABASE | gzip > $BACKUP_DIR/$DATETIME/$DATETIME.sql.gz
# 对整个临时备份文件夹进行打包
cd $BACKUP_DIR
tar -zcvf $DATETIME.tar.gz $DATETIME
# 删除临时文件夹
rm -rf $DATETIME
# 找到10天前的备份文件,进行删除
find $BACKUP_DIR -mtime +10 -name "*.tar.gz" -exec rm -rf {} \ # -exec表示执行,{} \是固定写法,表示找到的所有文件
echo "========备份结束=========="
# 指定凌晨2:10备份
crontab -e
10 2 * * * endgame.sh
service crond start
给Ubuntu的root用户设置密码
sudo passwd --> 输入普通用户的密码后就可以设置了之后就可以使用su命令切换到root用户