Linux学习笔记(更新中~)

Linux

1 Introduce

适用人群:

运维工程师(系统运维、应用运维、DBA)

开发工程师(内核/驱动开发、软件开发、嵌入式开发 )

架构师(进阶,性能调优、故障处理、…)

应用场景:

Web应用

数据库

大数据

云计算

物联网

图标: TUX(晚礼服的企鹅)

作者: Linus Torvalds(20岁发布0.01版本;学习大佬,成为牛人)

汇编语言 -> 操作机器语言(0/1)

狭义: linux kernel

广义: GNU/Linux

CentOS版本

2 History

源头: 贝尔实验室(Ken Thompson[Unix之父]/Dennis Ritchie)

Multics
Unix
BSD
FreeBSD
Darwin
MacOSX
Solaris
IBM-AIX
HP-UX
Minix
Linux

为了开发系统,发明了高级语言(基于ForTran语言发明了B语言,解释型语言),进而New B, 为了更直观,改名C语言。

大型系统一般适用UNIX,商业化(收费)

BSD: 伯克利软件套件

FreeBSD: 1993

Solaris: Sun公司,Oracle,对硬件依赖严重?

Minix: Andrew Tanenbaum

Linux源码公开,更改、发布后需要公开(Free)

源代码管理:

SVN

BitKeeper

Git

Github: 源代码交流平台

Richard Stallman

自由软件,GNU(1985)

GPL(1989)

保障个人开发自由

GNU核心: GNU/Hurd

Linux内核加入GNU (GNU/Linux, 能直接上手的linux)

GNU/Linux(计算机硬件 -> 硬件接口层[核心层kernel] -> 命令解释层 -> 外围应用层)

BSD

保障公司自由

Linux发行版

Linux发行版
RedHat
Debian
SUSE
Gentoo
ArchLinux
Android
HamonyOS
RedHatEnterpriseLinux
Rocky
Fedora
CentOS
Ubuntu
Mint
OpenSUSE
Manjaro
Deepin

Fedora: 新但是可能不稳定

CentOS: 免费

Debian: 社区类Linux

Ubuntu: 针对桌面有优化,Gnome,硬件兼容性强于CentOS,资源占用多

SUSE: 号称最华丽的OS,KDE

3 Base

OS: 操作计算机底层硬件的软件

OS启动流程

设备上电
BIOS固件
加载可引导设备中的GRUB
GRUB引导
加载硬盘分区中的OS文件
OS启动

安装系统时核心分区

  • /
  • swap (扩展内存,可挂载高速硬盘)
  • boot

4 FileSystem

文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。

4.1 常见类型

4.1.1 ext4

缩写:Fourth Extended Filesystem,第四代扩展文件系统的缩写

起源:2008

特点:

1、可靠,它是由比较老的代码生成的;

2、日志文件系统,对文件在磁盘中的位置以及任何其它对磁盘的更改做记录。如果系统崩溃,得益于journal技术,文件系统很少会损坏。

3、文件系统容量达到1EB,而文件容量达到了16TB. 理论上支持无限数量的子目录。除此以外,EXT4的分配器MBalloc还支持一次性调用分配多个数据块,

4、引入了盘区概念,每个盘区为一组连续的数据块,上述文件可以通过盘区的方式表示为“该文件数据保存在接下来的25600个数据块中”,提高了访问效率。

5、给日志数据添加了校验功能,日志校验功能可以很方便地判断日志数据是否损坏。

6、高性能,将ext3的两阶段日志机制合并成一个阶段,在增加安全性的同时提高了性能。日志总归会占用一些开销,ext4允许关闭日志,以便某些有特殊需求的用户可以借此提升性能

4.1.2 xfs

缩写:

起源:1993,由Silicon Graphics为他们的操作系统开发,之后被移植到Linux内核上。

特点:

1、特别擅长处理大文件,同时提供大型的数据传输。

2、对文件系统元数据提供了日志支持。当文件系统更新时,元数据会在实际的磁盘块被更新之前顺序写入日志。XFS的日志被保存在磁盘块的循环缓冲区上,不会被正常的文件系统操作影响。

3、64bit文件系统,最大支持 8EiB(exbibytes, 2^60 bytes)减1字节的单个文件系统,实际部署时取决于宿主操作系统的最大块限制。对于一个32bit Linux系统,文件和文件系统的大小会被限制在 16TiB(Tebibyte , 2^40 bytes) bytes。

最大容量: 8EB

4.1.3 区别

  • centos7默认文件系统是XFS,centos6是EXT4,cnetos5是EXT3.
  • ext4受限制于磁盘结构和兼容问题,可扩展性和scalability确实不如xfs
  • xfs是一种非常优秀的日志文件系统,它是SGI公司设计的。xfs被称为业界最先进的、最具可升级性的文件系统技术,
  • XFS是一个64位文件系统,理论上最大支持8EB减1字节的单个文件系统,实际部署时取决于宿主操作系统的最大块限制。

4.2 系统目录

/
/root
/bin
/boot
/dev
/etc
/home
/var
/lib
/usr
/medir
...
/usr/bin
/usr/lib
/usr/...

硬盘不同分区根据需要挂载到/(root)或者其他目录

相关概念:挂载点

/bin: binary, 存放经常使用的命令,一般是软链接,指向/usr/bin

/sbin: super user bin, 存放系统管理员使用的系统管理程序, 一般是软链接,指向/usr/sbin

/home: 存放普通用户的主目录,每个用户都有自己的一个目录,以用户名命名

/root: 系统管理员的用户主目录

/lib: 系统开机所需要的最基本的动态链接共享库,类似windows的dll文件(system32目录等). 一般是软链接,指向/usr/lib

/lib64:

/lost+found: 一般是空的,当系统非法关机后,会存放一些文件

/etc: 所有系统管理所需的配置文件和子目录

/usr: 用户的很多应用程序和文件都存放于此,类似于windows的program files目录

/boot: 存放启动linux时使用的一些核心文件,包括一些连接文件以及镜像文件

/proc: 虚拟目录,系统内存的映射,可以通过直接访问这个目录来获取系统信息

/srv: service, 存放一些服务启动之后需要提取的数据

/sys: linux2.6内核引入,安装了2.6内核中新出现的一个文件系统sysfs

/tmp: 存放临时文件

/dev: 类似windows设备管理器,把所有的硬件用文件的形式存储

/media(centos6): 识别设备后,将其挂载到该目录,centos7迁移至/run/media

/mnt: 用于用户临时挂载别的文件系统,可以将外部的存储挂载到/mnt/上,然后进入该目录就可以查看其内容

/opt: 用于给主机额外安装软件所存放的目录,默认空

/var: 存放不断扩充的文件,通常将经常被修改的目录存放于此,包括各种日志文件

5 VIM

vim = vi + 染色 + 语法检查 + …

编辑器之神

emacs 神之编辑器,作者:GNU创始人Richard Stallman,基于Lisp写的解释器

5.1 一般模式

默认模式

操作:移动、删除字符/整行、复制/粘贴

显示信息:坐标、百分比

常用语法:

语法 描述
yy 复制当前行
y[数字]y 复制n行
p 粘贴
u 撤销上一步
dd 删除当前行
d[数字]d 删除n行
x 剪切一个字母(del)
X 剪切一个字母(backspace)
yw 复制一个词
dw 删除一个词
shift+6(^) 移动至行头
shift+4($) 移动到行尾
w 切到下一个词头
e 切到下一个词尾
b 切到上一个词头
gg 页头
G 页尾
数字+shift+g 移动到n行头

5.2 编辑模式

从一般模式进入方式:i/a/o

离开方式:ESC

常用语法:

语法 描述
i 当前光标前
a 当前光标后
o 当前光标行的下一行
I 光标所在行最前
A 光标所在行最后
O 当前光标行的上一行

5.3 命令模式

从一般模式进入方式:‘:’ / ‘/’

离开方式:ESC / :q / :q! / :wq

主要操作:保存、退出编辑器

常用语法:

语法 描述
:set nu 显示行号
:set nonu 关闭行号
:w
:q
:wq
:! 强制执行
/word n查找下一个,N查找上一个
:noh 取消高亮显示
/old/new/g 替换当前行所有匹配内容
:%s/old/new/g 替换内容,/g替换匹配到的所有内容
/old/new 替换匹配到的第一个内容
:%s/old/new 替换每一行匹配到的第一个内容

注::s在部分markdown中会显示为表情,可以用:s代替,这个在csdn中好像无效

6 输入法

切换快捷键:shift+space

7 网络

7.1 查询

windows ip查询

方法1:cmd -> ipconfig

方法2:网络适配器 -> 以太网 -> 状态 -> 详细信息

linux ip查询

ifconfig

7.2 ping

场景1:虚拟机ping不通主机,但是主机能够ping虚拟机

打开主机的规则(防火墙->入站规则->文件和打印机共享回显请求专用公用)

7.3 网络连接模式

7.3.1 桥接模式

虚拟机直接连接外部物理网络的模式,主机起到网桥作用,虚拟机可以直接访问外部网络,并且对外部网络可见

7.3.2 NAT模式

虚拟机和主机构建一个专用网络,并通过虚拟网络地址转换(NAT)设备对IP进行转换。虚拟机通过共享主机IP可以访问外部网络,但外部网络没法访问虚拟机

7.3.3 仅主机模式

虚拟机只与主机共享一个专用网络,与外部网络无法通信

7.3 hosts

linux

hostname
hostnamectl [set-hostname new_name]

/etc/hostname

windows

C:\Windows\System32\driver\etc\hosts

修改hosts文件,可以使用主机名/域名代替ip

192.168.122.100 hadoop100
192.168.122.101 hadoop101
...

10.23.23.23 www.domain_name.com
ping hadoop100

注意:域名劫持

7.4 远程

#################################################################################

# /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0 #设置开机自动连接网络
allow-hotplug eth0
iface eth0 inet static #static表示固定ip , dhcp表示使用动态ip
address 192.168.3.x #设置ip地址
netmask 255.255.255.0 #设置子网掩码
network 192.168.3.0 #
broadcast 192.168.3.255
gateway 192.168.3.1 #设置网关

################################################################################

# /etc/resolv.conf
nameserver 192.168.3.1 # 一般和gateway的地址是一致的

#################################################################################

# 设置完重启服务或者重启,重启服务下面两个命令之一即可
service networking restart #重启网络
/etc/init.d/networking restart #记得sudo

#################################################################################

远程登陆工具:

xshell
SSH Secure Shell
SecureCRT
FinalShell

linux中的进程和服务

process: 计算机中一个正在执行的程序或命令
service: 启动后一只存在、常驻内存的process

传输文件

scp
xftp
...

7.5 服务

centos7使用NetworkManager

systemctl stop NetworkManager
systemctl disable NetworkManager

network和NetworkManager只需要存在一个running

7.6 相关操作

修改IP后可能遇到的问题

1 物理机能ping虚拟机,但是虚拟机不能ping物理机 =》 物理机防火墙没关
2 虚拟机能ping物理机,但是虚拟机不能ping外网 =》 DNS设置问题
3 虚拟机ping www.baidu.com 显示域名未知等信息 =》 查看GATEWAY和DNS设置是否正确
4 如果上述方法还是解决不了=》关闭NetworkManager服务
	systemctl stop NetworkManager
	systemctl disable NetworkManager
5 若检查发现systemctl status network有问题 =》 检查ifcfg-eth0

8 系统管理

8.1 service

命令

# centos6
service service_name start | stop | restart | status

# centos7
systemctl start | stop | restart | status service_name

查看当前启用服务

ls /etc/init.d/

# centos7
ls /usr/lib/systemd
ls /usr/lib/systemd/system/ # .service后缀

设置开机自启动服务

setup

SystemV

第一个启动的服务init

# centos6 只能串行启动,仅老版 systemV
chkconfig --list
chkconfig service_name on | off
chkconfig --level x service_name on | off

# centos7 并行
systemctl disable | enable | status | stop | restart service_name
systemctl list-unit-files # 状态: enable / disable / static(不确定,与其他有关联)

防火墙

老版本: iptables
新版本: firewalld

进程分类:前台、后台(守护进程,有后缀d)

1 系统服务
2 用户进程/服务

ps

ps [-euf] [aux] # 查看进程,-属于标准unix风格,不加-属于BSD风格
ps aux | less
ps -auhadoop # 查看hadoop进程
选项 说明
a 列出带有终端的所有用户的进程
x 列出当前用户的所有进程,包括没有终端的进程
u 面向用户友好的显示风格
-e 列出所有进程
-u 列出某个用户关联的所有进程
-f 显示完整格式的进程列表
[hadoop@hadoop001 Documents]$ bash
[hadoop@hadoop001 Documents]$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
hadoop    6102  6098  0 02:19 pts/2    00:00:00 -bash
hadoop    6455  6102  0 02:32 pts/2    00:00:00 bash # 父shell是-bash
hadoop    6497  6455  0 02:32 pts/2    00:00:00 ps -f
[hadoop@hadoop001 Documents]$ exit # 退出子shell
exit
[hadoop@hadoop001 Documents]$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
hadoop    6102  6098  0 02:19 pts/2    00:00:00 -bash
hadoop    6528  6102  0 02:33 pts/2    00:00:00 ps -f

VSZ 虚拟内存,不常用进程会被置换至虚拟内存,LRU(最近最少使用)

RSS 物理内存

TTY 终端,?代表没有终端,tty(tty1,图形化终端,tty2-6, 字符界面终端,pts/0-255,虚拟终端)

进程状态

stat 说明
S 睡眠状态
s 包含子进程
R 运行状态
T 暂停状态
Z 僵尸状态
l 小写l,多进程
+ 前台显示

START 启动时间

TIME 持续时间

PPID 父进程ID

systemd即init,PID=1,被系统级别进程(0)启动

场景

查看cpu占用率和内存占用率:aux

查看父进程:-ef

踢用户: ps 找到用户,kill

pstree

查看父进程等信息

pstree -p
pstree -u

kill

kill [option] process_id
killall service_name

kill -9 process_id
kill -l

killall sshd # 慎用,需要到设备上systemctl start sshd

top

top [option]
	-d 秒数 # 刷新时间,默认3秒
	-i # 不显示闲置或者僵死进程
	-p # 通过指定监控进程ID来仅监控某个进程

# 默认按CPU排序(P),按下M,则按memory排序;进程号(N);上下键可以翻页

k # 可以直接kill进程,+sig 比如9

# 回显
# %Cpu(s):  0.1 us,  0.0 sy,  0.0 ni, 99.8 id,  0.0 wa,  0.0 hi,  0.1 si,  0.0 st
# us(user) sy(system) ni(nice,调整优先级后的用户) id(idle) wa(wait) hi(hardware interrupt) si(software interrupt) st(stolen)

netstat

显示网络状态和端口信息

netstat -anp | grep process_id
netstat -nlp | grep port_id
	-a # 显示所有正在监听和未监听的套接字(进程间通信使用的)
	-n # 拒绝显示别名
	-l # 仅列出在监听的服务状态
	-p # 表示显示那个进程在调用

crontab

定时任务

crontab [option]
	-e 编辑crontab定时任务
	-l 查询crontab任务
	-r 删除当前用户所有的crontab任务

systemctl restart crond

* * * * * task_op
第一个* 一小时中的第几分钟 0-59
第二个* 一天中的第几小时 0-23
第三个* 一个月中的第几天 1-31
第四个* 一年中的第几个月 1-12
第五个* 一周中的周几 0-7 # 可以或

特殊符号:
* 任意
, 不连续
- 连续
*/n	每隔多久执行一次

8.2 运行级别 runlevel

开机
BIOS
/boot
init
运行类别
运行级别对应的服务

默认级别: /etc/inittab

常用运行级别

级别 描述
0 系统停机状态,系统默认运行级别不能设为0,否则不能启动
1 单用户工作状态,root权限,用于系统维护,禁止远程登陆
2 多用户状态(无NFS),不支持网络
3 完全的多用户状态(有NFS),登陆后进入控制台命令行模式
4 系统未使用,保留
5 X11控制台,登陆后进入图形GUI模式
6 系统正常关闭并重启,默认运行级别不饿能设为6,否则不能启动

注:常用级别为3/5

查看当前当前运行级别

systemctl get-default

9 常用命令

9.1 内置命令(built-in command)

内嵌于shell中,即linux源码中,系统加载启动之后随shell一起加载,常驻系统内存

基本命令:

help command_name
man [type] command_name
alias command_name
type command_name
history
exit
clear # 也可以使用 ctrl + l
reset # 重新初始化终端
pwd # 绝对路径
l. # ls -d .*
ls -i # vim修改文件后,索引会变化
echo # 输出到控制台, 连续多个空格会输出为一个,echo strings, echo "strings", 支持制表符(-e)
echo $ + tab # 查看环境变量

举例

man man
man -f cd
man 1p cd
man 1 cd
alias ll='ls -l --color=auto'

9.2 外部命令

除内置命令

rmdir [-p]
mkdir [-p]
rm
touch # vim 创建新文件借助文本编辑器,若没有新增,则不会创建新文件,与touch不同
\cp # 无提示,直接覆盖,使用linux原生命令  type cp -> cp -i
\rm
cat [-n]
more # 分屏查看,只能查看的简化版vi
less # 分屏查看,按需加载
head [-n] # 默认10行
tail [-n] # 默认10行
tail -f # 实时跟踪该文档的更新,应用场景:日志文件等持续增长且不会更改;起了一个进程挂起;ctrl+s 暂停 ctrl+q 继续 ctrl+c 退出
rm -rf link_name/ # 带/后缀会删除源目录下内容
ln [-s] src_file link_file # 如果不带s,则为硬链接 硬链接指向原inode,软链接创建一个新的文件指向
date
date +%Y
date +%y
date +%m
date +%d
date +%Y-$m-%d-%H:%M:%S # 自己定制显示格式,如果有空格,用""
date +%s # 当前秒数的时间戳,1970/1/1起始
date -d "1 days ago"
date -s "2017-06-19 20:52:52" # 设置当前时间
ntp date # 设置为网络时间
ntpdate src_link
cal

用户管理

useradd
id user_name
less /etc/passwd # 查看当前所有用户,可以看到系统用户(伪用户)
su # switch user
exit # 退出至上一个用户
who # 当前所有用户列表
who am i # 筛选当前用户信息
whoami
sudo # /etc/sudoers  new_user ALL=(ALL) ALL  ; 改进: new_user ALL=(ALL) 。组也可以设置 使用%开头
userdel
groupadd # /etc/group
usermod -g group_name user_name
groupmod -n new_group_name old_group_name
groupdel group_name
# wheel 管理员组
[root@hadoop001 scripts]# mesg
is y
[root@hadoop001 scripts]# who -T # 查看开启情况
hadoop   ? :0           2023-05-23 22:46 (:0)
hadoop   + pts/0        2023-05-23 22:49 (:0)
root     + pts/1        2023-05-30 01:12 (desktop-3nbdak0.mshome.net)

mesg n # 关闭mesg
mesg y # 开启mesg

[root@hadoop001 scripts]# who -T
hadoop   ? :0           2023-05-23 22:46 (:0)
hadoop   + pts/0        2023-05-23 22:49 (:0)
root     + pts/1        2023-05-30 01:12 (desktop-3nbdak0.mshome.net)
[root@hadoop001 scripts]# write hadoop pts/0
ffd
#!/bin/bash

# user is logining?
login_user=$(who | grep -i -m 1 $1 | awk '{print $1}')

if [ -z $login_user ]
then 
	echo "no user online"
	exit
fi


is_allowed=$(who -T | grep -i -m 1 $1 | awk '{print $2}')

if [ $is_allowed != "+" ]
then 
	echo "user:$1 not allowed"
	exit
fi


if [ -z $2 ]
then 
	echo "no message send"
	exit
fi


whole_msg=$( echo $* | cut -d " " -f 2- )

user_terminal=$( who | grep -i -m 1 $1 | awk '{print $2}' )

echo $whole_msg | write $login_user $user_terminal

if [ $? != 0 ] 
then 
	echo "send fail"
else
	echo "send success"
fi

文件管理

ll # 显示目录链接为2,因为目录下有./..
chmod [{ugoa}{+-=}{rwx}] file_name
chmod [mode=421] file_name
chmod -R 777 file_name # 递归
chown
chgrp
find [range] [option]
	option:name/user/size(b/c/w/k/M/G) # +10M 大于10M
locate # 利用事先建立的系统中所有文件名称及路径的locate数据库实现快速定位文件,无需遍历,速度快,但是依赖locate更新(updatedb)
which command_name
whereis command_name
grep [-n] target file_name
command | grep target # 联合使用
wc # word count, 行数 单词数 字节数 文件名

压缩

gzip/gunzip # 只能压缩文件,不能压缩目录;一个文件对应一个压缩文件;不保留原文件
zip [-r] # 可压缩目录
unzip [-d] # 可指定目录

tar [option] x.tar(x.tar.gz) files_name
	-c 产生.tar打包文件
	-v 显示详细信息
	-f 指定压缩后的文件名
	-z 打包同时压缩
	-x 解包.tar
	-C 解压到指定目录

磁盘管理

du # disk usage
	-h
	-a # 不仅查看子目录大小,还要包括文件
	-c 显示所有文件和子目录大小,显示总和
	-s 仅显示总和
	--max-depth=n # 指定统计子目录的深度
du -sh / # 不能显示所有的,只显示/分区
ls -lh # 仅统计文件夹本身大小,不会递归
df # disk free
# /dev/shm 共享内存空间(swap)

free -h # 查看内存

lsblk # 查看设备挂载情况, sda(sata、SCSI) / hda(IDE硬盘) / vda(虚拟化设备)
	-f 显示文件系统类型
	# UUID 系统为每个分区创建的唯一标识符
	# SCSI 小型计算机接口,一般在服务器中使用
	# SATA 串行ATA
	
mount/umount
mount [-t vfstype] [-o options] device mount_dir
# /etc/fstab # 所有设备挂载信息, 最后两个值(kdump(是否备份) 检查优先级(检查和修复文件系统优先级))
fsck # 检查和修复文件系统

fdisk -l # 查看硬盘分区详情,root
fdisk disk_name # 对新增硬盘进行分区操作, root,最多4个主分区,n个扩展分区
	fdisk /dev/sdb
lsblk -f # 查看文件系统类型
mkfs -t xfs /dev/sdb1
mount /dev/sdb1 /home/hadoop/

软件安装

# centos7
yum install software_name

10 软件包管理

RPM(Redhat Package Manager)

RPM包名称

Apache-1.3.23-11.i386.rpm

软件名-软件版本号(1.3.23-11).硬件平台(i386).扩展名(rpm)

rpm -qa # 查询所有安装的rpm包
rpm -qi package_name

rpm -e package # 卸载
rpm -e --nodeps package # 不检查依赖

rpm -i package
rpm -ivh package
mount /dev/cdrom /run/media
sudo mount /dev/cdrom /run/media
cd /run/media/
cd Packages/
ls | grep firefox
sudo rpm -ivh firefox-68.10.0-1.el7.centos.x86_64.rpm
rpm -qi firefox

YUM(Yellow dog Updater, Modify)

基于RPM,可以自动处理依赖关系

yum [option] [para]
	-y # 全部yes
	
	# para
	install
	update
	check-update
	remove
	list
	clean
	deplist # 显示依赖关系

修改YUM源

yum install wget
# /etc/yum.repos.d/CentOS-Base.repo
wget https://*** # 获取某个源

11 clone vm

当前还没用到

12 shell

12.1 解释

命令解释器

硬件
linux内核
shell
应用程序

12.2 查看

cat /etc/shells # 查看当前系统支持的shell,一般默认bash shell(RedHat系),dash(debian系)
echo $SHELL

12.3 shell脚本

开头

#!/bin/bash

执行方式

source x.sh # source built-in
bash x.sh

# 添加执行权限后
./x.sh # 相对路径
/x/.../x.sh # 绝对路径

# 错误用法
x.sh # 该方式会认为是命令

子shell中的变量,父shell不可见

点击ctrl+s后,界面会卡住,此时可以执行ctrl+d脱离此状态

系统预定义变量

$HOME
$PWD
$SHELL
$USER

显示当前shell所有变量

set

显示当前全局变量

env

查看变量

printenv var_name

其他示例

ls $HOME

自定义变量

var_name=val
unset var_name
readonly var_name # 不能unset

var_name="hello, world" # 单引号也可以
[hadoop@hadoop001 Documents]$ my_var='hell woo'
[hadoop@hadoop001 Documents]$ env | grep my_var
[hadoop@hadoop001 Documents]$ set | grep my_var
my_var='hell woo'
[hadoop@hadoop001 Documents]$ unset my_var

父bash中定义的变量,在子bash中不可见,除非全局变量

var_name=xxx
export var_name # 声明全局变量,提升,在这之前要定义变量
bash # 进入子shell
echo $var_name

子shell修改全局变量,仅在子shell中生效

export my_var

# x.sh中内容
#!/bin/bash
echo $my_var

source x.sh # 可以输出,在当前shell中执行
./x.sh # 可以输出,因为是全局变量

# x.sh中新增变量(非全局)
echo $new_var

./x.sh # new_var不输出
source x.sh # 可以输出new_var
. x.sh # 可以输出new_var

自定义用小写更合适,区别系统变量(大写)

变量名称可以由字母、数字和下划线组成,不能以数字开头,环境变量名建议大写

等号两侧不能有空格

bash中,默认字符串

my_var=1+5 # 按字符串形式
my_var=$((1+5)) # 按数值
my_var=$[1+5] # 按数值
[hadoop@hadoop001 Documents]$ readonly rb_var=5
[hadoop@hadoop001 Documents]$ echo $rb_var
5
[hadoop@hadoop001 Documents]$ rb_var=4
-bash: rb_var: readonly variable

# 删除只读变量方法
$ readonly PI=3.14
$ unset PI
-bash: unset: PI: cannot unset: readonly variable
$ cat << EOF| sudo gdb
attach $$
call unbind_variable("PI")
detach
EOF
$ echo $PI

直接执行x.sh的方法

mv x.sh /bin/ # 不推荐

PATH=$PATH:current_path

特殊变量

$n
#!/bin/bash
echo "=====$n======" # 不建议,双引号下会认为$n是特殊变量
echo '======$n====='
echo $0 # 脚本名字
echo $1 # 第一个参数
echo $2 # 第二个参数
echo $# # 参数个数
echo $* # 命令行所有参数,将所有参数看作一个整体
echo $@ # 命令行所有参数,区分对待,类似[p1, p2, p3]
echo $? # 最后一次命令返回值

shell不是高级语言,所以没法直接识别1+2等

expr 1 + 2 # 要有空格
expr 5 \* 2
$((1+2))
$[2+2]

命令替换

a=$(expr 5 \* 2)
echo $a

b=`expr 5 \* 3`
echo $b
#!/bin/bash
sum=$[$1 + $2]
echo sum=$sum

条件判断

[root@hadoop001 ~]# a=hello
[root@hadoop001 ~]# test $a = hello
[root@hadoop001 ~]# echo $?
0


# 另一种形式
[ condition ] # 前后要有空格

[ a = hello ] # =两端有空格,若都无空格,一定认为是真
echo $?

[ ] # 认为是假

[ a = b ] # 与高级语言==不同
[ a != b ] # 不支持>, < 具体逻辑实现: -gt, -ge等

[ -r x.sh ]
[ -x x.sh ]


&& # 逻辑与,为真则继续执行
|| # 逻辑或,为假则继续执行

系统函数

basename [string/pathname][suffix] # basename 会删除所有前缀,将字符串显示出来,指定后缀后,可以去掉后缀
dirname [absolute_path]

$0 # 绝对路径,如果只想显示文件名,可以使用$(basename $0) 或者 $(basename $0 .sh)
$(cd $(dirname $0); pwd)
#!/bin/bash

filename="$1"_log_$(date +%s) # 命令替换

echo $filename

自定义函数

[ function ] function_name[()] # []内可省略
{
	Action;
	[return int;]
}

# 必须在调用函数之前声明函数
# shell脚本逐行执行
# 函数返回值只能通过$?系统变量获得,如果定义函数时不加return,会返回最后一条命令运行结果,返回值范围(0-255)
#!/bin/bash

function add()
{
    s=$[ $1 + $2 ]
    echo $s
}

read -p "Enter first int: " a
read -p "Enter second int: " b

sum=$(add $a $b)
echo $sum

#!/bin/bash

# first, judge para num
if [ $# -ne 1 ]
then
	echo "para not enough"
	exit
fi

# second, get dir from para
if [ -d $1 ]
then
	echo "dirname valid"
else
	echo "dirname invalid"
	exit
fi

# third, 
DIR_NAME=$(basename $1)
DIR_PATH=$( cd $(dirname $1); pwd)
DATE=$(date +%y%m%d)
FILE=archive_${DIR_NAME}_$DATE.tar.gz
DST=/root/archive/$FILE

echo "begin archive"
tar -czf $DST $DIR_PATH/$DIR_NAME
if [ $? -eq 0 ]
then
	echo "archive success"
else
	echo "archive fail"
fi

exit


# 执行结果
[root@hadoop001 scripts]# ./archive.sh ../scripts/
dirname valid
begin archive
tar: Removing leading `/' from member names
archive success
[root@hadoop001 scripts]# ll ../archive/
total 8
-rw-r--r--. 1 root root 659 May 28 22:26 archive_scripts_230528.tar.gz
-rw-r--r--. 1 root root 666 May 28 22:25 archive_scripts+230528.tar.gz

12.4 正则

正则表达式使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。

常用处理工具:grep,sed,awk等

^ # 匹配某个开头的一行
cat /etc/passwd | grep ^a

$ # 匹配某个结尾的一行
cat /etc/passwd | grep t$

^xxx$ #全匹配
^$ # 匹配空行
grep -n ^$ # 显示空行号

. # 匹配一个任意字符
grep r..t

* # 某个字符出现任意多次,0-n,一般不单独出现
grep .* # 任意字符串
grep ^a.*bash$
grep ^a.*var.*in$

? # 某个字符出现任意多次,1-n

[] # 匹配中间的字符
grep [1,2] # 等价grep [12]
grep [1-4]

grep '\$' # 匹配$, 转义
grep '/\$' # 匹配/$

grep -E a{2} # 扩展规则,a匹配两次
echo "15033333333" | grep -E ^1[358][0-9]{9} # -E 显式声明扩展规则

文本处理

cut [option] filename
	-f # 列号
	-d # 分隔符,默认'\t'
	-c # 按字符进行切割,后面加n表示取第几列
	
cut -d " " -f 1 cut.txt

[root@hadoop001 scripts]# cat /etc/passwd | grep bash$ | cut -d ":" -f 1,6,7
root:/root:/bin/bash
hadoop:/home/hadoop:/bin/bash
add1:/home/add1:/bin/bash
hadoop002:/home/hadoop002:/bin/bash
hadoop003:/home/hadoop003:/bin/bash


cat /etc/passwd | grep bash$ | cut -d ":" -f 6- # 第6列之后都要

ifconfig | grep netmask | cut -d " " -f 10

awk

原名:gawk, gnu awk

文本分析工具,逐行读入,以空格为默认分隔符将每行切开

awk [option] '/pattern1/{action1} /pattern2/{action2}...' filename
	-F 指定输入文件分隔符
	-v 复制一个用户自定义变量
	# 是不是有-f???
cat /etc/passwd | grep ^root | cut -d ":" -f 7
# 等价形式,同时搞定行和列
cat /etc/passwd | awk -F ":" '/^root/{print $7}'

# 改进版
cat /etc/passwd | awk -F ":" '/^root/{print $1","$7}'

cat /etc/passwd | awk -F ":" '{print $1","$7}'

cat /etc/passwd | awk -F ":" 'BEGIN{print "user, shell"} {print $1","$7} END{print "end, lalala"}'

cat /etc/passwd | awk -F ":" '{print $3+1}'
cat /etc/passwd | awk -v i=1 -F ":" '{print $3+i}'

内置变量

变量 说明
FILENAME 文件名
NR 已读的记录数(行号)
NF 浏览记录的域的个数(切割后,列的个数)
cat /etc/passwd | awk -F ":" '{print "filename: "FILENAME" line_no: "NR" col: "NF}'

filename: - line_no: 41 col: 7 # -代表管道
# ...
filename: - line_no: 47 col: 7


ifconfig | grep -n ^$ # 有多余冒号
ifconfig | awk '/^$/{print NR}' 

ifconfig | awk '/netmask/{print $2}' # 优于grep

你可能感兴趣的:(linux,linux,学习,笔记)