在开发/部署过程中,我们经常要和Linux打交道,本文比较完整的整理了工作中的常用事项,包括常见命令、各种配置、中间件安装和shell脚本等内容,有助于我们系统的梳理Linux相关知识。如果从开发人员角度来说,能搞定了下面的内容,Linux方面就基本木有什么问题了。
对于Linux系统,我们首先应该了解它的相关目录结构,知道每个目录的定位与作用,下面列举主要的目录(我这里使用的CentOS 8版本)。
目录 | 说明 |
---|---|
/ | 根目录,Unix和Linux中没有盘符,一个硬盘对应一个根 |
/bin | 系统常用命令目录,包括控制台命令、系统可执行文件、系统核心二进制文件等 |
/etc | 发布目录,保存系统中所有核心内容,要求控制权限高,一般不要随意读写 |
/usr | 用户目录,相当于windows中的program files目录,常用于安装系统所有用户公用 |
/root | 根用户的用户目录,相当于windows中的administrator目录,称为用户主目录 |
/home | 保存其他用户目录的目录 |
/var | 系统运行过程中的数据目录 |
关于路径了解全路径(绝对路径)、相对路径和一些特殊路径符号就可以了。
路径 | 说明 |
---|---|
全路径 | 以 / 开头,从 filesystem 根目录开始寻找文件 |
相对路径 | 从当前资源路径开始寻找,找到其他资源路径过程,如 …/ 返回上一级 |
特殊路径 | / 表示磁盘根,~ 表示/root |
下面这些命令就是我们必须掌握的核心内容了,如何对linux中的资源进行增删改查,就靠它们了。
print working directory
,输出当前工作目录路径;
change directory
-,切换目录;
ls -a
查看所有内容,包括隐藏文件,全称
list all
;
ls -l
查看当前目录文件属性:大小、权限、日期、符号链接等,一般简写为
ll
,全称
list list
;
ls -al
多参数并行使用
touch 新文件名
,文件名可以没有后缀
touch /目录/新文件名
;
more 文件名
,按
空格键
显示下一屏幕内容,按
回车键
显示下一行内容,按
q或ctrl c
退出
head -行数 文件名
;
tail -行数 文件名
;
make directory
,创建目录
mkdir 新目录
mkdir /目录/新目录
mkdir -p 新目录1/新目录2
copy
,复制,格式
cp 源信息 目标信息
cp 源文件 复制文件
cp 源文件 /目录/复制文件
cp /目录/源文件 /目录/复制文件
-r
参数,
cp -r 目录 新目录
remove
,删除,格式
rm 文件
rm -f 文件
,
f
表示force 忽略,执行时不给出提示
rm -r 目录及文件
,
r
表示递归操作,删除目录及子目录和文件
rm -rf 目录及文件
move
,移动或重命名
mv 源文件 目标目录
mv 源文件 重命名新文件
vi 文件名
,进入编辑模式
dd
删除指定行, 默认 1 行,全称
delete line
:w
保存,
:q
退出,
:wq
保存并退出,全称
write quit
:q!
强制退出不保存
:set nu
显示行号
G
光标跳到文件尾,
gg
光标跳到文件头
/关键字
进行搜索
类型 | 拥有者权限 | 同组权限 | 其他权限 | 类型 | 拥有者 | 所在组 | 容量 | 时间 | 文件名 |
---|---|---|---|---|---|---|---|---|---|
d | rwx | r-x | r-x | 2 | root | root | 6 | May 29 03:10 | app目录 |
- | rw- | r– | r– | 1 | root | root | 0 | May 29 03:10 | readme.txt文件 |
类型为1表示文件,类型为2表示目录。rwx分别表示read、write、execut权限,-表示没有权限。容量单位是字节,所有目录固定容量为4096。
时区设置是很常用的操作,一般我们安装新系统后,都需要设置为当前时区,不然系统时间会有问题,下面就是具体操作步骤。
1、使用date
命令查看当前系统时间
2、使用tzselect
命令获取当前时区配置,并输入序号4
,选择Asia
地区
3、再选择9
,China
4、再选择1
,Beijing Time
5、再选择1
,Yes
确认提交修改
6、修改.bash_profile
文件,加入TZ='Asia/Shanghai';export TZ
配置设置时区
7、切换到当前用户目录下,使用ls -a
命令,可以找到.bash_profile
文件
8、vi .bash_profile
编辑文件,加入配置
9、使用exit
命令先注销用户,然后重新登录,使用date
命令查看,即可看到系统时间已经设置成功
说明:该时区方式只会对当前用户生效
CentOS8 中默认没有开始网络配置,所以我们需要手动开启
1、使用ifconfig
无法查看到ip地址,说明网络确实没有开启
2、先执行命令nmcli c up ens33
,再修改vi m /etc/sysconfig/network-scripts/ifcfg-ens33
配置,将ONBOOT
由no
设置为yes
3、再次查看则会显示ip地址
对于文件上传我们这里使用命令方式来操作,当然也可以借助其它工具(如Xftp)
1、需要安装lrzsz
插件,才能支持上传和下载,使用命令yum install lrzsz -y
2、上传
使用命令rz
,会弹出上传文件的窗口(r全称receive,表示linux服务器接收外部上传的文件资源)
3、下载
使用命令sz 文件名
,会弹出下载文件的窗口(s全称send,表示linux服务器向外发送文件资源)
开发过程中我们最常用的就是下面两种格式的压缩文件
1、*.tar.gz 格式
压缩tar.gz文件:使用命令tar -czvf 压缩文件的名称.tar.gz 源文件或者目录名称
解压tar.gz文件:使用命令tar -zxvf 解压文件名称
2、*.zip 格式
解压zip文件:使用命令unzip 压缩文件.zip
解压到指定目录:使用命令unzip 压缩文件.zip -d 解压到指定目录
1.1、上传安装包
在当前用户目录下,mkdir temp
新建一个临时目录存放安装包,再通过rz
命令,将JDK包上传到temp
目录中
1.2、解压
1)解压:使用命令tar -zxvf jdk-8u221-linux-x64.tar.gz -C /usr/local/
将jdk解压到/usr/local/
目录下
2)重命名:使用命令mv jdk1.8.0_221/ jdk
将其重命名为jdk
,方便后续配置
1.3、环境变量配置
vi /etc/profile
添加如下配置
export JAVA_HOME=/usr/local/jdk
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$JAVA_HOME/bin:$PATH
1.4、效果查看
reboot
重启系统后,使用java -version
查看版本(如果只要环境临时生效则使用source /etc/profile
命令)
2.1、上传安装包
将Tomcat安装包上传到temp
目录中
2.2、解压
1)解压:使用命令tar -zxf apache-tomcat-7.0.68.tar.gz -C /usr/local
解压到/usr/local/
目录下
2)重命名:使用命令mv apache-tomcat-7.0.68/ tomcat
将其重命名为tomcat
2.3、启动服务
1)切换目录:先 cd /usr/local/tomcat/bin/
到bin/
目录下,执行sh startup.sh
启动服务
2)然后再进入cd ../logs/
目录中,查看catalina.out
中的执行日志,如图表示启动成功
2.4、访问测试
因为linux默认只开启22端口,tomcat服务端口为8080,所以正常需要先开通8080端口防火墙才能访问,这里先直接关闭防火墙进行验证。
关闭防火墙:service firewalld stop
启动防火墙:systemctl enable firewalld
禁用防火墙:systemctl disable firewalld
3.1、上传安装包
将Mysql安装包上传到temp
目录中
3.2、解压
1)解压:使用命令tar -zxf mysql-5.7.27-linux-glibc2.12-x86_64.tar.gz -C /usr/local
解压到/usr/local/
目录下
2)重命名:使用命令mv mysql-5.7.27-linux-glibc2.12-x86_64/ mysql
将其重命名为mysql
3.3、创建用户组、用户
1)创建用户组:groupadd mysql
,表示创建一个名为mysql的用户组
2)创建用户:useradd -r -g mysql mysql
,/useradd -r mysql表示创建一个叫mysql的用户,-g表示将mysql用户添加到mysql用户组中
3.4、授权
1)切换目录:先cd /usr/local/mysql
到mysql/目录中
2)给用户组授权:chgrp -R mysql .
,用户组由root变成了mysql
3)给用户授权:chown -R mysql .
,用户由root变成了mysql
3.5、初始化
1)切换目录:先cd /usr/local/mysql/bin
到bin/
目录中
2)执行初始化命令:./mysqld --initialize --user=mysql --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/ --lc_messages_dir=/usr/local/mysql/share --lc_messages=en_US
,执行成功后,会在日志末尾生成一个密码串,需要copy保存下来
。
3.6、添加软连接
mysql5.7 要求系统中 libtinfo.so.5,如果CentOS 中的版本不一致(如libtinfo.so.6.1),则需要创建软连接
以上面版本为例,分别执行ln -s /usr/lib64/libtinfo.so.6 /usr/lib64/libtinfo.so.5
和ln -s /usr/lib64/libncurses.so.6 /usr/lib64/libncurses.so.5
命令
3.7、启动/开机自动启动
1)cd /usr/local/mysql/support-files/
到/support-files/
目录中
2)cp mysql.server /etc/init.d/mysql
复制mysql.server
执行文件到指定目录
3)service mysql start
启动服务
4)设置开启启动:systemctl enable mysql
3.8、修改root密码
1)添加 mysql 软连接:ln -s /usr/local/mysql/bin/mysql /usr/bin/mysql
2)连接客户端:mysql -u root -p
(这里需要输入的密码,就在3.5中初始化后的密码)
3)设置密码:set password=password(“自定义的密码”);
3.9、设置可访问客户端
1)给客户端授权:GRANT ALL PRIVILEGES ON *.* TO '用户名'@'%' IDENTIFIED BY '密码' WITH GRANT OPTION;
2)刷新权限:flush privileges;
3.10、使用工具连接(如navicat)
测试连接成功,如果连接不了,可以查看防火墙是否关闭(真实环境是开端口)
Shell 脚本(shell script)简单说也就是一些命令的集合,Linux 的 Shell 分类比较多,我们这里讲的是常用的 Bash( Bourne Again Shell的简称),它也是shell的解释器。
在文件头部声明#!/bin/bash
语句,下面是一个简单查看/usr/local
目录文件的脚本
[root@localhost shell]# cat test01.sh
#!/bin/bash
ls /usr/local
1、bash + 脚本文件
[root@localhost shell]# bash test01.sh
bin etc games include jdk lib lib64 libexec mysql sbin share src tomcat
2、source + 脚本文件
(使用当前的 bash 执行脚本,1和3是新启动一个子bash执行脚本)
[root@localhost shell]# source test01.sh
bin etc games include jdk lib lib64 libexec mysql sbin share src tomcat
3、./脚本文件.sh
(需要使用chmod +x 脚本文件.sh
授执行权限)
[root@localhost shell]# ./test01.sh
-bash: ./test01.sh: 权限不够
[root@localhost shell]# chmod +x test01.sh
[root@localhost shell]# ll
总用量 4
-rwxr-xr-x. 1 root root 27 6月 1 13:03 test01.sh
[root@localhost shell]# ./test01.sh
bin etc games include jdk lib lib64 libexec mysql sbin share src tomcat
IO有3种类型,分别为标准输入(值为0)、标准输出(值为1)和错误输出(值为2)
需要用到read
关键字,<<<
符号意思是将标准输入重定向到字符串中,可以理解为将test input str
值赋值给变量name
,然后再使用$name
方式取值
[root@localhost shell]# read name 0<<<"test input str"
[root@localhost shell]# echo $name
test input str
使用命令ls 1>/tmp/my.log
将当前目录的3个文件,以文本形式输入到了my.log日志文件中(一个>
符号是覆盖效果)
[root@localhost shell]# ll
总用量 4
-rw-r--r--. 1 root root 0 6月 1 13:58 1.txt
-rwxr-xr-x. 1 root root 27 6月 1 13:03 test01.sh
drwxr-xr-x. 2 root root 6 6月 1 14:00 tmp
[root@localhost shell]# ls 1>/tmp/my.log
[root@localhost shell]# cat /tmp/my.log
1.txt
test01.sh
tmp
使用命令ls 1>>/tmp/my.log
将当前目录的3个文件,以文本形式输入到了my.log日志文件中(两个>>
符号是追加效果)
[root@localhost shell]# ls 1>>/tmp/my.log
[root@localhost shell]# cat /tmp/my.log
1.txt
test01.sh
tmp
1.txt
test01.sh
tmp
使用命令ls /abc 2>>/tmp/error.log
,因为/abc
目录不存在,所有会将命令执行抛出的错误提示信息输入到error.log日志文件中
[root@localhost shell]# ls /abc 2>>/tmp/error.log
[root@localhost shell]# cat /tmp/error.log
ls: 无法访问'/abc': 没有那个文件或目录
常用写法为ls 1>>/tmp/my.log 2>&1
,表示先让标准输出重定向到my.log文件,然后将错误输出绑定到标准输出,这样正确与错误日志都会输出到my.log中
新建一个打印输出的简单脚本test02.sh
#!/bin/bash
myName=zhangsan
echo "myName的值为:"$myName
可见只能在脚本中执行才能获取变量值
[root@localhost shell]# bash test02.sh
myName的值为:zhangsan
[root@localhost shell]# echo $myName
[root@localhost shell]#
在test02.sh
定义一个打印变量yourName
,但是不在脚本中赋值
#!/bin/bash
myName=zhangsan
echo "myName的值为:"$myName
echo "yourName的值为:"$yourName
在外部使用export yourName=lisi
进行赋值,再执行bash test02.sh
,可见yourName
获取到了环境变量的值
[root@localhost shell]# export yourName=lisi
[root@localhost shell]# bash test02.sh
myName的值为:zhangsan
yourName的值为:lisi
在test02.sh
定义一个函数,则内部变量为局部变量
myfunc(){
myvar=99
echo $myvar
}
echo $myvar #访问不到
在test02.sh
定义两个参数输出
echo "参数1:"$1
echo "参数2:"$2
执行bash test02.sh wangwu zhaoliu
,表示执行脚本同时传入两个参数,分别对应$1
和$2
,然后会顺序打印输出
[root@localhost shell]# bash test02.sh wangwu zhaoliu
参数1:wangwu
参数2:zhaoliu
在test03.sh
中执行echo $#
#!/bin/bash
echo $#
执行脚本式传入3个参数,则会被脚本中的$#
获取参数个数
[root@localhost shell]# bash test03.sh a b c
3
双引号引用为一个字符串,如"a b c d e",所有的参数作为一个字符串,5 个参数作为一个字符串
双引号引用为单独的字符串, 如"a" “b” “c” “d” “e”,所有的参数作为单个的字符串,5 个参数作为五个字符串
$BASHPID
为当前pid的真实值
[root@localhost shell]# echo 'a' | echo $$
1822
[root@localhost shell]# echo 'a' | echo $BASHPID
2338
[root@localhost shell]# ps aux | grep bash
root 1822 0.0 0.6 26748 5196 pts/0 Ss 12:19 0:00 -bash
root 2340 0.0 0.1 12320 1040 pts/0 R+ 15:38 0:00 grep --color=auto bash
用来判断脚本中某个命令是否成功执行了
0
表示上个命令正常执行
[root@localhost shell]# ls
1.txt test01.sh test02.sh test03.sh tmp
[root@localhost shell]# echo $?
0
非0
表示上个命令非正常执行
[root@localhost shell]# ls /aabbcc
ls: 无法访问'/aabbcc': 没有那个文件或目录
[root@localhost shell]# echo $?
2
定义一个包含3个元素的数组name
[root@localhost shell]# name=('zhangsan' 'lisi' 'wangwu')
引用输出所有元素值,@
表示取所有值
[root@localhost shell]# echo ${name[@]}
zhangsan lisi wangwu
根据下标输出元素值,[数字]
表示下标,从0开始计算
[root@localhost shell]# echo ${name[1]} ${name[0]} ${name[2]}
lisi zhangsan wangwu
管道就是将左边命令的执行结果,作为标注输入到右边的命令,管道两边的命令在当前 shell 的两个子进程中执行。
ps aux | grep bash
就是一个管道用法,通过|
分隔左右两边命令,ps aux
表示显示当前系统所有进程
[root@localhost ~]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.5 1.6 178568 13460 ? Ss 22:53 0:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 17
root 2 0.0 0.0 0 0 ? S 22:53 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? I< 22:53 0:00 [rcu_gp]
root 4 0.0 0.0 0 0 ? I< 22:53 0:00 [rcu_par_gp]
root 5 0.1 0.0 0 0 ? I 22:53 0:00 [kworker/0:0-events_power_efficient]
root 6 0.0 0.0 0 0 ? I< 22:53 0:00 [kworker/0:0H-kblockd]
root 7 0.0 0.0 0 0 ? R 22:53 0:00 [kworker/u256:0-events_unbound]
root 8 0.0 0.0 0 0 ? I< 22:53 0:00 [mm_percpu_wq]
root 9 0.0 0.0 0 0 ? S 22:53 0:00 [ksoftirqd/0]
省略中间部分......
root 1792 0.0 1.1 93040 9456 ? Ss 22:55 0:00 /usr/lib/systemd/systemd --user
root 1796 0.0 0.5 238728 4736 ? S 22:55 0:00 (sd-pam)
root 1802 0.0 0.6 159416 5348 ? S 22:55 0:00 sshd: root@pts/0
root 1803 0.0 0.5 26360 4760 pts/0 Ss 22:55 0:00 -bash
root 1826 0.0 0.0 0 0 ? I 22:58 0:00 [kworker/0:1-mm_percpu_wq]
root 1838 0.0 0.4 57380 3772 pts/0 R+ 23:02 0:00 ps aux
grep bash
表示从左边获取到的所有进程结果中查看bash进程
[root@localhost ~]# ps aux | grep bash
root 1803 0.0 0.5 26360 4756 pts/0 Ss 22:55 0:00 -bash
root 1825 0.0 0.1 12320 1096 pts/0 R+ 22:57 0:00 grep --color=auto bash
双引号是弱引用,里面的内容支持参数引用。定义一个变量c
,在双引号中引用,可以输出变量$c
中的值
[root@localhost ~]# c="zhangsan"
[root@localhost ~]# echo "我是$c"
我是zhangsan
单引号是强引用,里面所有内容都被当成字符串,输出的只是变量符号本身$c
[root@localhost ~]# echo '我是$c'
我是$c
花括号可以做扩展,使用命令mkdir ./{a,b,c}dir
,可以同时创建3个目录,abc后面拼接了相同的dir
字符
[root@localhost shell]# mkdir ./{a,b,c}dir
[root@localhost shell]# ll
总用量 12
drwxr-xr-x. 2 root root 6 6月 1 23:17 adir
drwxr-xr-x. 2 root root 6 6月 1 23:17 bdir
drwxr-xr-x. 2 root root 6 6月 1 23:17 cdir
使用命令unset + 变量名
即可
[root@localhost shell]# echo $c
zhangsan
[root@localhost shell]# unset c
[root@localhost shell]# echo $c
[root@localhost shell]#
命令替换允许我们将 shell 命令的输出赋值给变量,方便使用。
定义一个变量a
,值是反引号包裹的查看命令ls -a
,再次引用时会执行该命令
[root@localhost shell]# a=`ls -a`
[root@localhost shell]# echo $a
. .. 1.txt adir bdir cdir test01.sh test02.sh test03.sh tmp
定义一个变量b
,值是$()
包裹的查看命令ls -a
,再次引用时会执行该命令
[root@localhost shell]# b=$(ls -a)
[root@localhost shell]# echo $b
. .. 1.txt adir bdir cdir test01.sh test02.sh test03.sh tmp
格式:command1 && command2,当第一个条件为假,第二个条件不用判断,结果为假
当前目录中有tmp目录
,第一个条件为真,所以会执行第二个打印条件
[root@localhost shell]# test -d /tmp && echo "tmp目录存在"
tmp目录存在
格式:command1 || command2,第一个条件为真,第二个条件不用判断,结果为真
tmp目录
下没有11目录
,第一个条件为假,所以会执行第二个打印条件
[root@localhost shell]# test -d /tmp/11 || echo "11目录不存在"
11目录不存在
常见有4种表达式写法:分别为let C=$A+$B
、C=`expr $A + $B`
、C=$[$A+$B]
与C=$((A+B))
,我们使用第一种let表达式举例说明。
新建一个test04.txt
文本,里面写入3行数据
[root@localhost shell]# cat test04.txt
aaaaaaa
bbbbbb
cccccc
再新建一个test04.sh
脚本,可以统计test04.txt
中文本行数,并且使用let表达式
判断出行数是奇数还是偶数
[root@localhost shell]# cat test04.sh
#!/bin/bash
#统计test04.txt中文本行数,wc统计行数,cut截取行数后面的字符,f1表示取第一个值
line_count=`wc -l test04.txt | cut -d " " -f1`
#判断行数是奇数还是偶数
let rs=line_count%2
[ $rs -eq 0 ] && echo "行数是偶数"
[ $rs -eq 1 ] && echo "行数是奇数"
执行脚本
[root@localhost shell]# bash test04.sh
行数是奇数
参数 | 说明 |
---|---|
-eq | 等于则为真 |
-ne | 不等于则为真 |
-gt | 大于则为真 |
-ge | 大于等于则为真 |
-lt | 小于则为真 |
-le | 小于等于则为真 |
单分支结构
if [ 条件判断 ]
then
//命令
fi
双分支结构
if [ 条件 1 ];then
条件 1 成立执行,指令集 1
else
条件 1 不成执行指令集 2;
fi
多分支结构
if [ 条件 1 ];then
条件 1 成立,执行指令集 1
elif [ 条件 2 ];then
条件 2 成立,执行指令集 2
else
条件都不成立,执行指令集 3
fi
语法格式
for 变量 in 列表 ; do
语句
done
举例:新建test05.sh
脚本,并编写一段循环累加的计算求和代码
[root@localhost shell]# cat test05.sh
#!/bin/bash
# 计算从1累加到n的值,n大于等于1
sum=0
# 先判断传入参数是否合法
if [ $# -ne 1 ];then
echo "参数个数不对"
exit 2
else
if [ $1 -le 1 ];then
echo "参数不能小于或等于1"
exit 3
fi
fi
# 变量求和
for i in `seq 1 $1`;do
let sum=sum+i
done
echo "总和为:$sum"
执行脚本
[root@localhost shell]# bash test05.sh 10 20
参数个数不对
[root@localhost shell]# bash test05.sh -10
参数不能小于或等于1
[root@localhost shell]# bash test05.sh 10
总和为:55
非死循环:也支持使用break
关键字跳出循环
while 条件;do
语句
[break]
done
死循环:使用while true
或while:
或while [0]
等都是死循环,如下面示例
while true
do
语句
done
语法格式
case $变量名称 in “值 1")
程序段 1
;;
“值 2")
程序段 2
;;
*)
exit 1
;;
esac
举例:新建test06.sh
脚本,根据输入数值,输出对应星期几
[root@localhost shell]# cat test06.sh
#!/bin/bash
read -p "please input a number[1,7]:" num
case $num in
1)
echo "Mon"
;;
2)
echo "Tue"
;;
3)
echo "Wed"
;;
4)
echo "Thu"
;;
5)
echo "Fir"
;;
[6-7])
echo "weekend"
;;
*)
echo "please input [1,7]"
;;
esac
执行脚本
[root@localhost shell]# bash test06.sh
please input a number[1,7]:6
weekend
看到了这里,那我们对于Linux系统的基本用法,应该已经有整体性解了~