Linux操作系统
Linux基本概况
Linux 是一套免费使用和自由传播的类 Unix 操作系统,基于C语言和汇编语言综合开发,是一个基于 POSIX 和 UNIX 的多用户、多任务、支持多线程和多 CPU 的操作系统。
- 基础教程: https://www.runoob.com/linux/linux-tutorial.html
- 命令大全: https://www.runoob.com/linux/linux-command-manual.html
架构
进程管理、进程调度、时间管理和定时器、系统调用接口、内存寻址、内存管理和页缓存、VFS、内核同步、移植性相关的问题以及调试技术。
PING
PING,Packet Internet Groper,因特网包探索器,用于测试网络连接量的程序。
- ping ip,如果不能成功
cd /etc/sysconfig/network-scripts/ # 进入目录
vim ifcfg-ens33 # 打开文件
将ONBOOT=no 改成ONBOOT= yes # 选项设置
service network restart # 重启服务
- PING失败
网线刚插到交换机上就Ping通网关,忽略了生成树的收敛时间。当然,较新的交换机都支持快速生成树,或者有的管理员干脆把用户端口(accessport)的生成树协议关掉,问题就解决了。 不管中间经过了多少个节点,只要有节点(包括端节点)对ICMP信息包进行了过滤,Ping不通是正常的。最常见的就是防火墙的行为。 某些路由器端口是不允许用户Ping的。 网络因设备间的超时,造成ICMP报文无法在缺省时间(2秒)内收到。超时的原因有:主机没有足够的时间和资源来响应;路径太长,没到达目的地时TTL的值为0,最后一个路由器将发回ICMP超时信息;使用扩展Ping,增加应答等待时间间隔等。 引入NAT的场合会造成单向Ping通。NAT可以起到隐蔽内部地址的作用,当由内Ping外时,可以Ping通是因为NAT表的映射关系存在,当由外发起Ping内网主机时,就无从查找边界路由器的NAT访问列表了。
软连接
软连接也称为符号链接,软连接类似于 Windows 中的快捷方式,允许你创建指向另一个文件或目录的指针。
- 可以简化文件和目录的管理。
- 允许你创建指向其他文件或目录的指针,而不会复制文件内容,从而节省了磁盘空间。
文件目录
├─ C
│ ├─ C1
│ │ └─ input.txt
│ └─ C2
├─ D
└─ E
指令列表
> ls --help
# 创建
> ln -s [目标文件或目录] [软连接名]
# 创建指向input.txt的软链接
> cd C/C1
> ln -s input.txt link_to_input.txt
# 修改
> ln –snf [新的源文件或目录] [目标文件或目录]
# 删除
> rm –rf [软链接名称]
# 查看
> ls -il
---------------------------------------------------------------------------
参数 描述
---------------------------------------------------------------------------
-b 删除,覆盖以前建立的链接
-d 允许超级用户制作目录的硬链接
-f 强制执行
-i 交互模式,文件存在则提示用户是否覆盖
-n 把符号链接视为一般目录
-s 软链接(符号链接)
-v 显示详细的处理过程
---------------------------------------------------------------------------
硬连接与软连接
硬连接
硬连接(hard link)是指文件系统中的一个文件引用(链接)到相同的物理数据块。硬连接允许多个文件名指向同一个文件数据。
优先选择硬链接
当需要节省存储空间、防止数据误删或同一文件系统的多入口访问时。
多个名称指向同一个文件数据:硬连接创建多个文件名,它们指向相同的数据块。这意味着修改其中任何一个文件的内容,其他链接文件的内容也会随之变化。
删除原文件不影响数据:删除一个硬连接并不会删除文件数据,只有当所有硬连接都被删除时,文件数据才会被实际删除。
不适用于目录:通常,硬连接不能用于目录(除非使用一些特殊的工具或技术)。
直接指向文件数据块。
不能跨文件系统。
不能指向目录。
文件名之间是等价的,删除一个不会影响数据,除非所有硬连接都被删除。
# 创建
> ln [目标文件] [硬连接名]
# 创建指向input.txt的软链接
> cd C/C1
> ln input.txt link_to_input.txt
# 删除硬链接
> rm link_to_input.txt
软连接(符号链接)
为某一个文件在另外一个位置建立一个同步的链接。
优先选择软连接
当需要跨文件系统、链接目录或创建动态路径时。
当我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在某个固定的目录,放上该文件,然后在 其它的目录下用ln命令链接(link)它就可以,不必重复的占用磁盘空间。
指向文件路径。
可以跨文件系统。
可以指向目录。
删除软连接不会影响目标文件,但删除目标文件后软连接会变为无效。
# 创建命令
ln -s <目标路径> <链接名称>
-s:表示创建软连接(符号链接)。
-f:强制覆盖已存在的链接。
-i:覆盖前提示确认
# 删除链接,仅删除链接本身,不影响目标文件
rm <链接名称>
# 检查软连接状态
ls -l
ls -l <链接名称>
# 检查目标可达性
readlink <链接名称>
# 访问软连接
> 通过软连接访问目标文件或目录,与操作普通文件一致
# 为本地文件创建软连接
ln -s /home/user/data/file.txt /home/user/links/file_link # 将file.txt链接到links目录
# 为目录创建软连接
ln -s /var/www/html /home/user/web # 将Web目录链接到用户目录
环境变量
环境变量用于在不同的进程之间传递配置信息。
指令列表
# 查看环境变量
> printenv # 方法一
> env # 方法二
# 查看某个特定的环境变量
> echo $PATH # 查看 PATH 变量
# 临时设置环境变量,新增、修改或删除环境变量,仅限于该次登陆操作
export [-fnp][变量名称]=[变量设置值]
-f 代表[变量名称]中为函数名称。
-n 删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行环境中。
-p 列出所有的shell赋予程序的环境变量。
> export VARIABLE_NAME="some_value"
# 验证变量是否已设置
> echo $VARIABLE_NAME
# 删除环境变量
> unset VARIABLE_NAM
# 永久设置环境变量
> 将它们添加到配置文件中,如 ~/.bashrc、~/.bash_profile、~/.profile 或 /etc/profile 等。
# 将这些变量添加到 ~/.bashrc 以便永久生效
echo 'export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64' >> ~/.bashrc
echo 'export PATH=$JAVA_HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
MacOS
/Users/apple/.profile
/Users/apple/.bash_profile
/Users/apple/.bashrc
/Users/apple/.zshenv
相关文件
系统环境变量:/etc/environment 环境变量文件:vim /etc/profile 用户环境变量:vim ~/.bash_profile -> /etc/profile -> ~/.profile
查看系统变量 export
设置变量
在/etc/profile文件中添加变量 ( 对所有用户永久生效 在用户目录下的.bash_profile文件中增加变量 ( 对单一用户永久生效 直接在shell运行export命令定义变量 ( 只对当前shell(BASH)临时有效
PATH声明格式
export PATH=$PATH:<PATH 1>:<PATH 2>:<PATH 3>:------:<PATH N>
export PATH=$PATH:~/npm
export PATH=${JAVA_HOME}/bin:$PATH
# 在第一行添加
export JAVA_HOME=/home/app/java/jdk1.8.0_381
export PATH=${JAVA_HOME}/bin:$PATH
# 在最后一行添加
export PATH=$PATH:${JAVA_HOME}/bin
- 激活环境变量文件 | 立即生效
source /etc/profile
- 注意,如何在/etc/profile配置全局变量后发现某个变量的值还是不对,则通过以下操作查看与解决
查看所有PATH配置:export 修改文件:/root/.bashrc # 找出需要删除的选项删除则可 source /root/.bashrc
操作环境变量
# 查看环境变量
echo $PATH
# 修改环境变量
export PATH=/root/anaconda3/bin:/root/anaconda3/bin:/root/anaconda3/condabin:/root/anaconda3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/bin/git/bin:/root/bin
权限管理
- chmod命令:https://www.runoob.com/linux/linux-comm-chmod.html
权限等级
- 文件所有者(Owner)
- 用户组(Group)
- 其它用户(Other Users)
基础语法
chmod [-cfvR] [--help] [--version] mode file...
u(g | o | a) u 表示该文件的拥有者,g 表示与该文件的拥有者属于同一个群体(group)者,o 表示其他以外的人,a 表示这三者皆是。
+(+ | - | =) + 表示增加权限、- 表示取消权限、= 表示唯一设定权限。
r(r | w | x | X) r 表示可读取,w 表示可写入,x 表示可执行,X 表示只有当该文件是个子目录或者该文件已经被设定过为可执行。
-c 若该文件权限确实已经更改,才显示其更改动作
-f 若该文件权限无法被更改也不要显示错误讯息
-v 显示权限变更的详细资料
-R 对目前目录下的所有文件与子目录进行相同的权限变更(即以递归的方式逐个变更)
--help 显示辅助说明
--version 显示版本
系统管理
Linux文件目录
|-/bin __(__ Binaries (二进制文件) 命令
|-/boot __(__ Linux启动依赖的连接文件以及镜像文件
|-/dev __(__ Linux的Device(外部设备)
|-/etc __(__ Linux的配置文件和子目录。
|-/lib __(__ Linux的动态连接共享库Library(库) ,类似于Windows系统DLL 文件
|-/root __(__ 超级权限管理目录
|-/usr __(__ 用户的应用程序和文件unix shared resources(共享资源)
|-/usr/bin __(__ 系统用户使用的应用程序
|-/usr/sbin __(__ 超级用户使用的比较高级的管理程序和系统守护程序
|-/usr/src __(__ 内核源代码默认的放置目录
|-/tmp __(__ 临时文件目录
|-/proc __(__ 当前内核运行状态的一系列特殊文件
|-/var __(__ 存储variable(变量) 日志等文件。
|-/run __(__ 存储系统启动依赖的临时文件系统。
|-/home __(__ 用户主目录
系统信息
# 查看系统位数
> getconf LONG_BIT
# 查看系统的名称、内核版本和硬件架构
> uname -a
# 显示内容
Linux iv-ydq54v5ssgwuxjsenvhp 5.15.120-4.ve2.x86_64 #1 SMP Tue Jul 30 09:51:48 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
Linux hecs-86065 5.10.0-60.18.0.50.r509_2.hce2.x86_64 #1 SMP Sat Oct 8 13:01:36 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
# 仅查看内核版本
> uname -r
# 显示内容
5.10.0-60.18.0.50.r509_2.hce2.x86_64
# 仅查看系统名称
``` sh
> uname -s
# 显示内容
Linux
# 操作系统的详细信息,如名称、版本等
> cat /etc/os-release
# 显示内容
NAME="Huawei Cloud EulerOS"
VERSION="2.0 (x86_64)"
ID="hce"
VERSION_ID="2.0"
PRETTY_NAME="Huawei Cloud EulerOS 2.0 (x86_64)"
ANSI_COLOR="0;31"
# 显示和设置主机名,还提供了一些基本的系统信息
> hostnamectl
# 显示内容
Static hostname: hecs-86065
Icon name: computer-vm
Chassis: vm
Machine ID: 9b7085d7e1bc4970827b539b0e7eb2d5
Boot ID: 3f85f9bbff2b4c6eb0066714ea057c6f
Virtualization: kvm
Operating System: Huawei Cloud EulerOS 2.0 (x86_64)
Kernel: Linux 5.10.0-60.18.0.50.r509_2.hce2.x86_64
Architecture: x86-64
Hardware Vendor: OpenStack Foundation
Hardware Model: OpenStack Nova
内存管理
> free -h
# 显示内容
total used free shared buff/cache available
Mem: 7.3Gi 1.3Gi 5.1Gi 10Mi 790Mi 5.6Gi
total: 系统总内存(RAM)或交换空间(swap)的总量。
used: 已被使用的内存或交换空间的量,此值包含 buff/cache,因此实际“活跃使用”的内存可能更低。
free: 当前未被使用的内存或交换空间的量,此值为纯未使用内存,但现代系统会主动利用空闲内存作为缓存以提高性能。
shared: 与其他进程共享的内存量。
buff/cache: 被内核用于缓存和缓冲的内存量,这部分内存可以在需要时被释放。
available: 预计可以用作新的应用程序或进程的内存量,即使没有立即释放的内存。
# 这个命令每秒刷新一次 free -h 的输出,方便实时监控内存使用情况。
> watch -n 1 free -h
磁盘管理
- https://www.runoob.com/linux/linux-filesystem.html
# df: 列出文件系统的整体磁盘使用量
> df -h
# 显示内容
Filesystem Size Used Avail Use% Mounted on
devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs 3.7G 0 3.7G 0% /dev/shm
tmpfs 3.7G 8.6M 3.7G 1% /run
tmpfs 4.0M 0 4.0M 0% /sys/fs/cgroup
/dev/vda1 40G 36G 1.3G 97% /
tmpfs 3.7G 36K 3.7G 1% /tmp
环境变量
> export PATH="$PATH:/usr/local/bin/python3.5"
> path=%path%;C:\Python #配置环境变量
> export ANDROID_HOME=/usr/local/share/android-sdk/ #导入环境变量
# 查看环境变量
> export
# 删除环境变量
> vim /etc/profile
文件与内容管理
路径
/etc/hosts #hosts路径 clear | reset #清除当前屏幕显示 pwd #显示当前目录, 例如/Users/ysun/project/server whereis [name] #查看所有软件路径安装位置, 例如whereis python which [name] #查看当前使用软件路径, 例如which python
检索文件夹中所有文件的内容
cat *js | grep '淘宝逛逛'
grep '小红书'
grep
用于查找文件里符合条件的字符串或正则表达式
- 需要保证文件名或文件路径正确,否则在在不匹配的情况下,返回不是空值。
# 从指定文件中查询字符串
grep 'erp-static/image/favicon.ico' /home/erp_fe/index.html
解压文件
unzip [.zip] # 解压ZIP格式文件 tar zxvf [.gz] [.tgz] tar xvJf [.xz] cp -r [pcre-8.35] [pcre] #拷贝且重定义文件名 mv [A] [B] #将A重命名为B mv [pcre] [../software] #移动文件至/home/software/
压缩文件
tar -cvzf [压缩后文件.tar.gz] [源文件]
查看目录文件
-a 显示所有文件及目录 (. 开头的隐藏文件也会列出)
-l 除文件名称外,亦将文件型态、权限、拥有者、文件大小等资讯详细列出
-r 将文件以相反次序显示(原定依英文字母次序)
-t 将文件依建立时间之先后次序列出
-A 同 -a ,但不列出 "." (目前目录) 及 ".." (父目录)
-F 在列出的文件名称后加一符号;例如可执行档则加 "*", 目录则加 "/"
-R 若目录下有文件,则以下之文件亦皆依序列出
# 查看目录文件
> ls ./
# 查看目录文件(包含隐藏的文件)
> ls ./ -a
操作文件
> stat [文件名] 查看文件信息,大小
> ls: # 列出目录, 例如: ls ./
> cd: # 切换目录, 例如: cd ../
> pwd: # 显示目前的目录, 例如: pwd
> mkdir: # 创建一个新的目录, 例如: mkdir -p name
> rmdir: # 删除一个空的目录, 例如: rmdir name
> rm: # 移除文件或目录, 例如: rm -rf name
# 移动文件与目录,或修改文件与目录的名称
> mv:
> mv keepalived-2.0.10 /usr/local/src/
# 修改文件
> touch: # 创建文件, 例如: touch list.txt
> rm -rf * # 删除文件夹下的所有文件,而不删除文件夹本身
移动文件或文件夹
> mv [options] source... [dest | directory]
> options参数
-b: 当目标文件或目录存在时,在执行覆盖前,会为其创建一个备份。
-i: 如果指定移动的源目录或文件与目标的目录或文件同名,则会先询问是否覆盖旧文件,输入 y 表示直接覆盖,输入 n 表示取消该操作。
-f: 如果指定移动的源目录或文件与目标的目录或文件同名,不会询问,直接覆盖旧文件。
-n: 不要覆盖任何已存在的文件或目录。
-u:当源文件比目标文件新或者目标文件不存在时,才执行移动操作。
# 修改file.text为name.text
> mv file.text name.text
# 修改文件夹
> mv folder_name new_folder_name
# 将文件夹test移动到文件夹object中
> mv /Users/apple/Downloads/test /Users/apple/Downloads/object
复制文件或文件夹
指令:cp [options] [source] [dest]
> options参数
-a:此选项通常在复制目录时使用,它保留链接、文件属性,并复制目录下的所有内容。其作用等于dpR参数组合。
-d:复制时保留链接。这里所说的链接相当于 Windows 系统中的快捷方式。
-f:覆盖已经存在的目标文件而不给出提示。
-i:与 -f 选项相反,在覆盖目标文件之前给出提示,要求用户确认是否覆盖,回答 y 时目标文件将被覆盖。
-p:除复制文件的内容外,还把修改时间和访问权限也复制到新文件中。
-r:若给出的源文件是一个目录文件,此时将复制该目录下所有的子目录和文件。
-l:不复制文件,只是生成链接文件。
> 目录结构
├─ home
│ ├─
│ ├─
├─ test
│ ├─ index.js
│ ├─
> 示例一:cp -r -f /test /home # 把目录/test(包括test当前文件夹)拷贝到目录/home,最后目录为/home/test
> 示例二:cp -r -f /test/index.js /home # 把目录/test文件夹中的index.js拷贝到目录/home,最后目录为/home/index.js
> 示例三:cp -r -f /test/* /home/wangjun # 把目录/test文件夹中的所有文件拷贝到目录/home/test,最后目录为/home/test/*
# 注意:只有带上斜杠才不会出现cp: overwrite提示
> \cp -rfp
复制文件并修改文件名
> \cp -rfp /test/index.js /test/test.js
> \cp -rfp /data/home/wangjun/erp.js /data/home/wangjun/list.js
cp -rf /System/Library/Fonts /Users/apple/Downloads/fitness_common_server/static
统计文件夹中文件数量
> ls -l |grep "^-"|wc -l # 文件夹下文件总数
> ls -l |grep "^d"|wc -l # 文件夹下目录总数
> ls -lh # 查看文件夹大小
统计文件夹下的文件个数
> ls -l | grep "^-" | wc -l # 统计当前目录下文件的个数(不包括目录)
> ls -lR| grep "^-" | wc -l # 统计当前目录下文件的个数(包括子目录)
> ls -lR | grep "^d" | wc -l # 查看某目录下文件夹(目录)的个数(包括子目录)
文件夹或文件检索
> find / -type d -name "folder_name" # 检索某个文件夹名称所在路径
> find . -name "filename.txt" # 从当前目录检索某个文件所在路径
基础指令
Port端口管理
> netstat -ntlp # 查看所有端口 | netstat -anp
> netstat -ntulp |grep [port] # 查看所有指定端口使用情况
> fuser -k -n tcp [port] # 关闭指定端口
# 端口被占用
> 步骤一:lsof -i tcp:[port] | 获取PID号
> 步骤二:kill -15 [PID] | 绝杀
# windows系统查看端口占用情况
> 打开CMD命令行,输入:netstat -ano 示例:协议 本地地址 外部地址 状态 PID (TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 46036)
> 找到相关端口对应的PID
> 按Ctrl + Shift + Esc打开任务管理器,选择"详细信息",找到对应PID,单击右下角"结束任务"即可。
IP管理
> ip a # 查看IP
> ip addr # 查看IP
> ifconfig -a # 查看IP
> ipconfig /all # windows
# 结果如下所示
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 52:54:00:32:8e:a4 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.2/24 brd 10.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe32:8ea4/64 scope link
valid_lft forever preferred_lft forever
服务管理
systemctl命令
systemctl命令兼容了service,systemctl命令管理systemd的资源Unit, 目录/lib/systemd/system/
# 基础命令
> systemctl --version __(__ 查看systemctl版本
> systemctl list-unit-files __(__ 列出所有可用单元
> systemctl list-units __(__ 列出所有运行中单元
> systemctl daemon-reload __(__ 更新配置
# 管理服务
> systemctl start [NAME] __(__ 启动
> systemctl restart [NAME] __(__ 重新启动
> systemctl reload [NAME] __(__ 重新载入配置
> systemctl stop [NAME] __(__ 停止
> systemctl enable [NAME] __(__ 加入开机启动
> systemctl disable [NAME] __(__ 禁止开机启动
> systemctl status [NAME] __(__ 查看状态
> systemctl show [NAME] __(__ 显示服务详细信息
service命令
是在/etc/init.d/目录中创建一个脚本文件,来管理服务的启动和停止
> service redis start #/etc/init.d/redis start
systemd服务
systemd是Linux系统最新的初始化系统,作用是提高系统的启动速度。CentOS 7.x开始使用systemd服务。
开机自启动
# 方式一
> 在脚本/etc/rc.d/rc.local(和/etc/rc.local是同一个文件,软链)末尾添加自己的脚本,然后,增加脚本执行权限
> 给脚本添加执行权限:chmod +x /etc/rc.d/rc.local
# 方式二
> 编写shell脚本,将其添加到/etc/init.d目录中
# Linux目录
> /etc/rc.local:添加启动程序的shell脚本
> /etc/rc.d/rc.local:与/etc/rc.local是同一个文件,软连接关系
> /etc/init.d:将自己的用户脚本添加到/etc/init.d并链接到自启动程序当中
> /etc/profile:当用户第一次登录时,该文件被执行. 并从/etc/profile.d目录的配置文件中搜集shell的设置
# 在/etc/rc.local中追加开机自启动脚本
> vim /etc/rc.local
hosts配置管理
SwitchHosts(管理和一键切换多个 hosts 方案的免费开源工具):https://swh.app/
# windows 修改hosts文件即时更新
10.8.24.36
> 查看DNS缓存:ipconfig /displaydns
> 清空DNS缓存:ipconfig /flushdns
# Mac OS 修改hosts文件即时更新 | 打开"访达"窗口,点按键盘快捷键Shift + Command + G,输入"ect/hosts",即可看到hosts位置。 /private/etc/hosts
> sudo dscacheutil -flushcache
# 不同系统hosts位置
> Windows系统:C:\Windows\System32\drivers\etc\hosts
> Mac系统:/etc/hosts
> Linux系统:/etc/hosts
> Android系统:/system/etc/hosts
> iOS系统:/etc/hosts
# Linux 修改hosts文件即时更新
> 使用NSCD的DNS缓存机制:sudo /etc/init.d/nscd restart
> 使用DNSMASQ的服务器或路由器:sudo dnsmasq restart
# Chrome清除缓存
> 地址栏:chrome://net-internals/#dns
# Linux修改hosts
> E45: 'readonly' option is set (add ! to override)
> 解决::wq!
# Linux
> vim /etc/hosts
> /etc/hosts.allow
> /etc/hosts.deny
# win10
> C:\Windows\System32\drivers\etc
sudo rm -f /etc/.hosts.swp
# ------------------------
# hosts
# ------------------------
# ------------------------
# hosts.allow
# ------------------------
# ------------------------
# hosts.deny
# ------------------------
进程/性能/内存/CPU/空间
系统
# 查看Linux系统版本
> cat /etc/issue 或者 lsb_release -a
# 查看系统
> cat /etc/os-release
# 查看操作系统版本
> uname -r
# 查看CentOS版本
> cat /etc/redhat-release
# 查看系统内核
> cat /proc/version
# 查看系统内核
> uname -a
# 单个CPU逻辑物理核数 查看系统信息,例如CPU几核
> cat /proc/cpuinfo
--------------------------------------------------------------------------------------------------
siblings 单个CPU逻辑物理核数
--------------------------------------------------------------------------------------------------
内存管理
# 查看内存信息
> free -b(以Byte为单位显示内存使用情况) | -k(KB)| -m(MB)| -g(GB)| -h(合适)
# 查看系统空间,例如内存大小 | MemTotal | MemFree | MemAvailable | Buffers | Cached
> cat /proc/meminfo
实时监控
> watch -n 1 free -h
查看前十进程服务
> ps aux --sort=-%mem | awk '{printf "%s %s %s %s %s %.2fG %s %s %s %s %s\n", $1, $2,$3, $4, $5, $6/1024/1024, $7, $8, $9, $10, $11}' | head -n 10
进程
ps -A(显示所有进程) | a(显示终端中包括其它用户的所有进程) | x(显示无控制终端的进程)
查看某系统服务进程
# 查看redis进程,ps -ef | grep redis
> ps -ef | grep NAME
# 关闭进程
> kill PID
显卡
> lspci | grep -i vga
00:02.0 VGA compatible controller: Cirrus Logic GD 5446
任务管理器
# 实时显示 process 的动态 | 查看CPU状态
> top #按 q 退出
PID USER PR NI BIRI RES SHR S %CPU %MEM
6980 root 20 0 967000 107820 72368 S 0.7 2.7
磁盘管理
df -h
-------------------------------------------------------------
文件系统 容量 已用 可用 已用% 挂载点
-------------------------------------------------------------
Filesystem Size Used Avail Use% Mounted on
-------------------------------------------------------------
devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 3.9G 640K 3.9G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/vda1 40G 18G 21G 46% /
tmpfs 799M 0 799M 0% /run/user/0
-------------------------------------------------------------
文件夹与文件占用空间
# 当前目录占用空间
> du -sh
# 当前目录所有文件与文件夹占用空间列表
> du -sh *
资源管理
字体
# 查看Linux已安装字体
fc-list
# 查看Linux已安装中文字体
fc-list lang:zh
> windows字体目录: C:\Windows\Fonts
安装中文字体
# 建立新目录
/usr/share/fonts/myfonts
cp /home/download/* /usr/share/fonts/myfonts/ # 拷贝字体文件到该目录
cd /usr/share/fonts/,执行 chmod -R 755 /usr/share/fonts/Fonts/ # 修改字体文件权限
yum install mkfontscale # 安装字体索引指令
yum install fontconfig # 安装 fc-cache 指令
mkfontscale && mkfontdir && fc-cache -fv # 建立字体索引信息,更新字体缓存
网络管理
Bridged-Host-only-NAT
网络模式
Bridged 桥接模式
Bridged(桥接模式):将主机网卡与虚拟机虚拟的网卡利用虚拟网桥进行通信。Bridge 桥"就是一个主机,这个机器拥有两块网卡,分别处于两个局域网中,同时在"桥"上,运行着程序,让局域网A中的所有数据包原封不动的流入B,反之亦然。这样,局域网A和B就无缝的在链路层连接起来了,在桥接时,VMWare网卡和物理网卡应该处于同一IP网段 当然要保证两个局域网没有冲突的IP. VMWare 的桥也是同样的道理,只不过,本来作为硬件的一块网卡,现在由VMWare软件虚拟了!当采用桥接时,VMWare会虚拟一块网卡和真正的物理网卡就行桥接,这样,发到物理网卡的所有数据包就到了VMWare虚拟机,而由VMWare发出的数据包也会通过桥从物理网卡的那端发出。
Host-only 主机模式
Host-only(主机模式):Host-Only模式将虚拟机与外网隔开,使得虚拟机成为一个独立的系统,只与主机相互通讯。
NAT 桥接模式
NAT(网络地址转换模式):NAT 是 Network address translate的简称。NAT技术应用在internet网关和路由器上,比如192.168.0.123这个地址要访问internet,它的数据包就要通过一个网关或者路由器,而网关或者路由器拥有一个能访问internet的ip地址,这样的网关和路由器就要在收发数据包时,对数据包的IP协议层数据进行更改(即 NAT),以使私有网段的主机能够顺利访问internet。此技术解决了IP地址稀缺的问题。同样的私有IP可以网关NAT 上网。 VMWare的NAT上网也是同样的道理,它在主机和虚拟机之间用软件伪造出一块网卡,这块网卡和虚拟机的ip处于一个地址段。同时,在这块网卡和主机的网络接口之间进行NAT。虚拟机发出的每一块数据包都会经过虚拟网卡,然后NAT,然后由主机的接口发出。
ifcfg-ens33.conf
#DEVICE 接口名(设备,网卡)
#USERCTL [yes|no](非root用户是否可以控制该设备)
#BOOTPROTO IP的配置方法[none|static|bootp|dhcp](引导时不使用协议|静态分配IP|BOOTP协议|DHCP协议)
#HWADDR MAC地址
#ONBOOT 系统启动的时候网络接口是否有效(yes/no)
#TYPE 网络类型(通常是Ethemet)
#NETMASK 网络掩码
#IPADDR IP地址
#IPV6INIT IPV6是否有效(yes/no)
#GATEWAY 默认网关IP地址
#BROADCAST 广播地址
#NETWORK 网络地址
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp #手动,静态IP(none/static) 还是自动(dhcp)
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=2f2dbec9-82a1-4667-8f03-286f6adf0a85
DEVICE=ens33
ONBOOT=yes #网卡设备自动启动
PEERDNS=yes
PEERROUTES=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_PRIVACY=no
IPADDR=192.168.222.2 #本机IP地址
NETMASK=255.255.255.0 #子网掩码
DNS1=202.96.134.133 #DNS服务器列表
DNS2=202.96.128.166
iptables.conf
#防火墙
#位置:/etc/sysconfig/iptables
#防火墙操作
> systemctl status firewalld #查看防火墙状态,出现以下信息含有Active: active (running),则说明已开启
> systemctl start firewalld #启动
> systemctl stop firewalld #关闭防火墙, 但是系统重启后会开启
> systemctl disable firewalld #永久禁止防火墙
> systemctl enable firewalld #开机启用
firewall-cmd --zone=public --add-port=8080/tcp --permanent
module.service
# 不能存放注释, 实际配置请删除
# 配置中使用相对路径则会报错
[Unit] #服务描述
Description=Process Monitoring and Control Daemon #描述服务
After=rc-local.service #服务类别
[Service] #服务的一些具体运行参数的设置
Type=forking
ExecStart=/usr/local/bin/forever start /node.js/xiyoulib/bin/www #启动命令
ExecReload=/usr/local/bin/forever restart /node.js/xiyoulib/bin/www #重启命令
ExecStop=/usr/local/bin/forever stop /node.js/xiyoulib/bin/www #停止命令
SysVStartPriority=99
PrivateTmp=True #给服务分配独立的临时空间
ExecStart=/redis-4.0.6/src/redis-server /redis-4.0.6/redis.conf --daemonize no
ExecStop=/redis-4.0.6/src/redis-cli -h 127.0.0.1 -p 6379 shutdown
[Install] #服务安装的相关设置
WantedBy=multi-user.target
netcard
#网卡
|-/etc/sysconfig/network-scripts/ifcfg-ens33
【基础指令】
> 重启网卡:/etc/init.d/service network restart
通信网络
|-etc/
|-/etc/sysconfig/network-scripts/
【常用指令】
> ip addr:查看或设定网络接口
> ipconfig:查看或设定网络接口
> ping `<IP>`:检测网络状况
>
>
〖操作网络〗
> systemctl stop NetworkManger:停止网络记录服务
> systemctl restart network:重启网络
> systemctl start NetworkManger:打开网络记录服务
>
【IP地址】
【网关】
【DNS】
Linux 命令大全
文件管理
cat
chattr
chgrp
chmod
chown
cksum
cmp
diff
diffstat
file
find
git
gitview
indent
cut
ln
less
locate
lsattr
mattrib
mc
mdel
mdir
mktemp
more
mmove
mread
mren
mtools
mtoolstest
mv
od
paste
patch
rm
slocate
split
tee
tmpwatch
touch
umask
which
whereis
mcopy
mshowfat
rhmask
cp
rcp
# 用于 Linux 之间复制文件和目录
scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]
[-l limit] [-o ssh_option] [-P port] [-S program]
[[user@]host1:]file1 [...] [[user@]host2:]file2
scp [选项] [源文件] [目标路径]
完整选项说明:
-1: 强制scp命令使用协议ssh1
-2: 强制scp命令使用协议ssh2
-4: 强制scp命令只使用IPv4寻址
-6: 强制scp命令只使用IPv6寻址
-B: 使用批处理模式(传输过程中不询问传输口令或短语)
-C: 允许压缩。(将-C标志传递给ssh,从而打开压缩功能)
-p:保留原文件的修改时间,访问时间和访问权限。
-q: 不显示传输进度条。
-r: 递归复制整个目录。
-v:详细方式显示输出。scp和ssh(1)会显示出整个过程的调试信息。这些信息用于调试连接,验证和配置问题。
-c cipher: 以cipher将数据传输进行加密,这个选项将直接传递给ssh。
-F ssh_config: 指定一个替代的ssh配置文件,此参数直接传递给ssh。
-i identity_file: 从指定文件中读取传输时使用的密钥文件,此参数直接传递给ssh。
-l limit: 限定用户所能使用的带宽,以Kbit/s为单位。
-o ssh_option: 如果习惯于使用ssh_config(5)中的参数传递方式,
-P port:注意是大写的P, port是指定数据传输用到的端口号
-S program: 指定加密传输时所使用的程序。此程序必须能够理解ssh(1)的选项。
awk
# 从标准输入读取数值,例如读取键盘值
read [-ers] [-a aname] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
-a 后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符。
-d 后面跟一个标志符,其实只有其后的第一个字符有用,作为结束的标志。
-p 后面跟提示信息,即在输入前打印提示信息。
-e 在输入的时候可以使用命令补全功能。
-n 后跟一个数字,定义输入文本的长度,很实用。
-r 屏蔽\,如果没有该选项,则\作为一个转义字符,有的话 \就是个正常的字符了。
-s 安静模式,在输入字符时不再屏幕上显示,例如login时输入密码。
-t 后面跟秒数,定义输入字符的等待时间。
-u 后面跟fd,从文件描述符中读入,该文件描述符可以是exec新开启的。
updatedb
文档编辑
col colrm comm csplit
ed egrep ex fgrep
fmt fold grep ispell
jed joe join look
mtype pico rgrep sed
sort spell tr expr
uniq wc let
文件传输
lprm lpr lpq lpd
bye ftp uuto uupick
uucp uucico tftp ncftp
ftpshut ftpwho ftpcount
磁盘管理
cd df dirs du
edquota eject mcd mdeltree
mdu mkdir mlabel mmd
mrd mzip pwd quota
mount mmount rmdir rmt
stat tree umount ls
quotacheck quotaoff lndir repquota
quotaon
磁盘维护
badblocks cfdisk dd e2fsck
ext2ed fsck fsck.minix fsconf
fdformat hdparm mformat mkbootdisk
mkdosfs mke2fs mkfs.ext2 mkfs.msdos
mkinitrd mkisofs mkswap mpartition
swapon symlinks sync mbadblocks
mkfs.minix fsck.ext2 fdisk losetup
mkfs sfdisk swapoff
网络通讯
apachectl arpwatch dip getty
mingetty uux telnet uulog
uustat ppp-off netconfig nc
httpd ifconfig minicom mesg
dnsconf wall netstat ping
pppstats samba setserial talk
traceroute tty newaliases uuname
netconf write statserial efax
pppsetup tcpdump ytalk cu
smbd testparm smbclient shapecfg
系统管理
adduser chfn useradd date
exit
finger fwhios
# 将目前动作延迟一段时间
sleep [--help] [--version] number[smhd]
--help : 显示辅助讯息
--version : 显示版本编号
number : 时间长度,后面可接 s、m、h 或 d
# 其中 s 为秒,m 为 分钟,h 为小时,d 为日数
suspend groupdel groupmod halt
kill last lastb login
logname logout ps nice
procinfo top pstree reboot
rlogin rsh sliplogin
# 多重视窗管理程序
screen
screen [-AmRvx -ls -wipe][-d <作业名称>][-h <行数>][-r <作业名称>][-s <shell>][-S <作业名称>]
-A 将所有的视窗都调整为目前终端机的大小。
-d<作业名称> 将指定的screen作业离线。
-h<行数> 指定视窗的缓冲区行数。
-m 即使目前已在作业中的screen作业,仍强制建立新的screen作业。
-r<作业名称> 恢复离线的screen作业。
-R 先试图恢复离线的作业。若找不到离线的作业,即建立新的screen作业。
-s<shell> 指定建立新视窗时,所要执行的shell。
-S<作业名称> 指定screen作业的名称。
-v 显示版本信息。
-x 恢复之前离线的screen作业。
-ls或--list 显示目前所有的screen作业。
-wipe 检查目前所有的screen作业,并删除已经无法使用的screen作业。
shutdown rwho sudo gitps
swatch tload logrotate uname
chsh userconf userdel usermod
vlock who whoami whois
newgrp renice su skill
w id groupadd free
系统设置
reset clear alias dircolors
aumix bind chroot clock
crontab declare depmod dmesg
enable eval export pwunconv
grpconv rpm insmod kbdconfig
lilo liloconfig lsmod minfo
set modprobe ntsysv mouseconfig
passwd pwconv rdate resize
rmmod grpunconv modinfo time
setup sndconfig setenv setconsole
timeconfig ulimit unset chkconfig
apmd hwclock mkkickstart fbset
unalias SVGATextMode gpasswd
备份压缩
ar bunzip2 bzip2 bzip2recover
gunzip unarj compress cpio
dump uuencode gzexe gzip
lha restore tar uudecode
unzip zip zipinfo
设备管理
setleds loadkeys rdev dumpkeys
MAKEDEV poweroff
Shell
Shell 是一个用 C 语言编写的程序。
运行 Shell 脚本
# 方式一:作为可执行程序,需在第一行指定解释器信息:#!/bin/bash
> ./test.sh
> /home/meta/List/Shell/test.sh
> chmod 777 /home/meta/List/Shell/test.sh # 如果存在权限问题,则使用该指令
# 方式二:作为解释器参数, 例如
> /bin/sh test.sh
> /bin/php test.php
开机自启动
> /etc/rc.local #软连接
> /etc/rc.d/rc.local #源文件
权限
# 编写脚本
# 把脚本放在/etc/init.d/
# 为脚本设置可执行权限
> chmod +x [SHELL_NAME]
> ll [SHELL_NAME]
> chkconfig [SHELL_NAME] on #添加开机自启动
> /etc/init.d/[SHELL_NAME] start #测试
# 常见问题
> ./example.sh报错:-bash: ./example.sh: Permission denied
> chmod 777 example.sh
shell脚本示例
# 终止执行
exit -1
注释
# 以 # 开头的行就是注释,会被解释器忽略
# 多行注释
:<<EOF
注释内容...
注释内容...
注释内容...
EOF
# 直接使用 : 号
> : + 空格 + 单引号
: '
这是注释的部分。
可以有多行内容。
'
变量
- 变量名不加美元符号。
- 变量名和等号之间不能有空格。
- 只包含字母、数字和下划线。
- 不能以数字开头。
- 避免使用 Shell 关键字。
- 使用大写字母表示常量。
- 避免使用特殊符号。
- 避免使用空格。
APP_VERSION="1.0.0"
app_name="附近货"
# 二次赋值
APP_VERSION="1.0.1"
# 读取变量
echo $your_name # 写法一
echo ${your_name} # 写法二,为了解决这种边界 echo "${skill}Script"
# 只读变量
name="张三"
readonly name
# 报错:/bin/sh: NAME: This variable is read only.
name="李四"
# 删除变量,不能删除只读变量
unset variable_name
# 整数变量
> 使用 declare 或 typeset 命令来声明整数变量,如果尝试将非整数值赋给它,Shell会尝试将其转换为整数。
declare -i my_integer=42
# 环境变量
echo $PATH
# 特殊变量
+ $0 表示脚本的名称
+ $1, $2, 等表示脚本的参数
+ $# 表示传递给脚本的参数数量
+ $? 表示上一个命令的退出状态等
# 单引号
> 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效。
str='this is a string'
# 双引号
> 双引号里可以有变量,双引号里可以出现转义字符。
str="Hello, I know you are \"$your_name\"! \n"
# 拼接字符串
your_name="runoob"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3
# 获取字符串长度
string="abcd"
echo ${#string}
# 提取子字符串:第一个字符的索引值为 0
> 从字符串第 2 个字符开始截取 4 个字符
string="runoob is a great site"
echo ${string:1:4} # 输出 unoo
# 查找子字符串
> 查找字符 i 或 o 的位置(哪个字母先出现就计算哪个)
string="runoob is a great site"
echo `expr index "$string" io` # 输出 4
数组
Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小。
# 整数索引数组
my_array=(1 2 3 4 5)
array_name=(
value0
value1
value2
value3
)
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
my_array=(A B "C" D)
# 仅仅输出数组中第一个值
echo "${my_array}"
echo "第一个元素为: ${my_array[0]}"
echo "第二个元素为: ${my_array[1]}"
echo "第三个元素为: ${my_array[2]}"
echo "第四个元素为: ${my_array[3]}"
# 关联数组
declare -A associative_array
associative_array["name"]="John"
associative_array["age"]=30
# 创建一个关联数组 site,并创建不同的键值
declare -A site=(["google"]="www.google.com" ["runoob"]="www.runoob.com" ["taobao"]="www.taobao.com")
# 先声明一个关联数组,然后再设置键和值
declare -A site
site["google"]="www.google.com"
site["runoob"]="www.runoob.com"
site["taobao"]="www.taobao.com"
# 读取数组
> ${数组名[下标]}
valuen=${array_name[n]}
# 使用 @ 或 * 可以获取数组中的所有元素
echo ${array_name[@]}
echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}"
# 获取数组的长度
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
length=${#array_name[n]}
# 在数组前加一个感叹号 ! 可以获取数组的所有键
declare -A site
site["google"]="www.google.com"
site["runoob"]="www.runoob.com"
site["taobao"]="www.taobao.com"
echo "数组的键为: ${!site[*]}"
echo "数组的键为: ${!site[@]}"
运算符
使用$(())或$(expr)实现运算,具体见如下示例。
num=$((num - 1))
echo "使用 $(( )) 自减后: $num"
# 使用 expr 命令
num1=$(expr $num + 1)
echo "使用 expr 自增后: $num1"
- 表达式和运算符之间要有空格
- 完整的表达式要被 ` ` 包含
- 乘号(*)前边必须加反斜杠 /* 才能实现乘法运算:
# expr 是一款表达式计算工具,使用它能完成表达式的求值操作
val=`expr 2 + 2`
echo "两数之和为 : $val"
算数运算符
条件表达式要放在方括号之间,并且要有空格
# ------------------------------------------------------------
运算符 说明 举例
# ------------------------------------------------------------
+ 加法 `expr $a + $b` 结果为 30。
- 减法 `expr $a - $b` 结果为 -10。
* 乘法 `expr $a \* $b` 结果为 200。
/ 除法 `expr $b / $a` 结果为 2。
% 取余 `expr $b % $a` 结果为 0。
= 赋值 a=$b 把变量 b 的值赋给 a。
== 相等。 用于比较两个数字,相同则返回 true。 [ $a == $b ] 返回 false。
!= 不相等。用于比较两个数字,不相同则返回 true。 [ $a != $b ] 返回 true。
# ------------------------------------------------------------
a=10
b=20
val=`expr $a + $b`
echo "a + b : $val"
val=`expr $a - $b`
echo "a - b : $val"
val=`expr $a \* $b`
echo "a * b : $val"
val=`expr $b / $a`
echo "b / a : $val"
val=`expr $b % $a`
echo "b % a : $val"
if [ $a == $b ]; then
echo "a 等于 b"
fi
if [ $a != $b ]; then
echo "a 不等于 b"
fi
关系运算符
# ------------------------------------------------------------
运算符 说明 举例
# ------------------------------------------------------------
-eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
-ne 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。
# ------------------------------------------------------------
布尔运算符
# ------------------------------------------------------------
运算符 说明 举例
# ------------------------------------------------------------
! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
-o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。
# ------------------------------------------------------------
逻辑运算符
必须加双括号:[[ ]]
# ------------------------------------------------------------
运算符 说明 举例
# ------------------------------------------------------------
&& 逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
|| 逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true
# ------------------------------------------------------------
a=10
b=20
if [[ $a -lt 100 && $b -gt 100 ]]; then
echo "返回 true"
else
echo "返回 false"
fi
if [[ $a -lt 100 || $b -gt 100 ]]; then
echo "返回 true"
else
echo "返回 false"
fi
字符串运算符
# ------------------------------------------------------------
运算符 说明 举例
# ------------------------------------------------------------
= 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 检测两个字符串是否不相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
-n 检测字符串长度是否不为 0,不为 0 返回 true。 [ -n "$a" ] 返回 true。
$ 检测字符串是否不为空,不为空返回 true。 [ $a ] 返回 true。
# ------------------------------------------------------------
文件测试运算符
# ------------------------------------------------------------
操作符 说明 举例
# ------------------------------------------------------------
-b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
-c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
-d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
-g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。
-p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
-u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
-r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
-w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
-x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
-e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。
# ------------------------------------------------------------
其他检查符
- -S file: 判断某文件是否 socket。
- -L file: 检测文件是否存在并且是一个符号链接。
自增和自减操作符
# 初始化变量
num=5
echo "初始值: $num"
# 使用 let 命令
# 自增
let num++
echo "自增后: $num"
# 自减
let num--
echo "自减后: $num"
# 使用 $(( )) 进行算术运算
num=$((num + 1))
echo "使用 $(( )) 自增后: $num"
num=$((num - 1))
echo "使用 $(( )) 自减后: $num"
# 使用 expr 命令
num=$(expr $num + 1)
echo "使用 expr 自增后: $num"
num=$(expr $num - 1)
echo "使用 expr 自减后: $num"
# 使用 (( )) 进行算术运算
((num++))
echo "使用 (( )) 自增后: $num"
((num--))
echo "使用 (( )) 自减后: $num"
echo命令
# 显示普通字符串
echo "It is a test"
# 显示转义字符
echo "\"It is a test\""
# 显示变量
read name
echo "$name It is a test"
# 显示换行
echo -e "OK! \n" # -e 开启转义
# 显示不换行
echo -e "OK! \c" # -e 开启转义 \c 不换行
# 显示结果定向至文件,即将内容写入到指定文件中
echo "It is a test" > myfile
echo "shell脚本" > /home/meta/List/Shell/input.txt
# 空设备
# 原样输出字符串,不进行转义或取变量(用单引号)
echo '$name\"'
# 显示命令执行结果
echo `date`
printf 命令
高亮日志
# 日志
OWN_DOCKER_COLOR_RED='\033[0;31m' # 红色(普通)
OWN_DOCKER_COLOR_GREEN='\033[0;32m' # 绿色
OWN_DOCKER_COLOR_YELLOW='\033[0;33m' # 黄色
OWN_DOCKER_COLOR_BLUE='\033[0;34m' # 蓝色
OWN_DOCKER_COLOR_BOLD_RED='\033[1;31m' # 红色加粗
OWN_DOCKER_COLOR_NC='\033[0m' # 重置颜色
# 错误日志
error() {
echo -e "\n${OWN_DOCKER_COLOR_RED}[错误] ${OWN_DOCKER_COLOR_NC} $1 \n";
}
# 警告日志
warn() {
echo -e "\n${OWN_DOCKER_COLOR_YELLOW}[警告] ${OWN_DOCKER_COLOR_NC} $1 \n";
}
# 信息日志
info() {
echo -e "\n${OWN_DOCKER_COLOR_GREEN}[信息] ${OWN_DOCKER_COLOR_NC} $1 \n";
}
# 调试日志
debug() {
echo -e "\n${OWN_DOCKER_COLOR_BLUE}[调试] ${OWN_DOCKER_COLOR_NC} $1 \n";
}
进度条UI
# 简单百分比进度条
total=100
for ((i=1; i<=total; i++)); do
printf "\rProgress: [%-50s] %d%%" $(printf "#%.0s" $(seq 1 $((i*50/total)))) $((i*100/total))
sleep 0.1
done
echo -e "\nDone"
# 分段式进度条
#!/bin/bash
i=0
bar=''
while [ $i -le 100 ]; do
printf "[%-100s] %d%% \r" "$bar" "$i"
sleep 0.1
((i=i+2))
bar+='#'
done
echo
# 动态未知进度条(无明确终点)
#!/bin/bash
arr=('|' '/' '-' '\') # 旋转符号数组
index=0
while true; do
printf "Processing %c\r" "${arr[index]}"
index=$(( (index+1) % 4 ))
sleep 0.2
done
# 动态填充替换
#!/bin/bash
length=20
ratio=1
while true; do
progress_bar=''
for ((j=1; j<=length; j++)); do
[ $j -le $ratio ] && progress_bar+='=' || progress_bar+='-'
done
printf "Progress: [%s]\r" "$progress_bar"
ratio=$(( (ratio % length) + 1 ))
sleep 0.1
done
# 颜色与样式美化
printf "\e[34m[%-50s]\e[0m %d%%\r" "$bar" "$i" # 蓝色进度条[2](@ref)
# 直接显示管道数据进度(无需脚本循环)
pv -pteb large_file.tar | tar xf - # 解压时显示进度[6](@ref)
# 使用 --progress 选项同步文件
rsync -av --progress source/ destination/ # 显示每个文件传输进度[6](@ref)
# 信号处理
trap 'kill $!; echo -e "\nAborted"; exit' INT
(while true; do ... done) & # 后台运行进度条
# 完整示例(带颜色和旋转标记)
#!/bin/bash
total=100
bar=''
colors=('\e[31m' '\e[32m' '\e[33m') # 红、绿、黄
spin=('|' '/' '-' '\')
for ((i=0; i<=total; i++)); do
# 进度条填充
bar+='#'
# 计算颜色和旋转符号
color_idx=$((i % 3))
spin_idx=$((i % 4))
# 打印带颜色的进度条
printf "\r${colors[color_idx]}[%-100s]%d%% ${spin[spin_idx]}\e[0m" "$bar" "$i"
sleep 0.1
done
echo -e "\nComplete"
test 命令
用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
# 数值测试
# ------------------------------------------------------------
参数 说明
# ------------------------------------------------------------
-eq 等于则为真
-ne 不等于则为真
-gt 大于则为真
-ge 大于等于则为真
-lt 小于则为真
-le 小于等于则为真
# ------------------------------------------------------------
num1=100
num2=100
if test $[num1] -eq $[num2]
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi
# 字符测试
# ------------------------------------------------------------
参数 说明
# ------------------------------------------------------------
= 等于则为真
!= 不相等则为真
-z 字符串 字符串的长度为零则为真
-n 字符串 字符串的长度不为零则为真
# ------------------------------------------------------------
num1="ru1noob"
num2="runoob"
if test $num1 = $num2
then
echo '两个字符串相等!'
else
echo '两个字符串不相等!'
fi
# 文件测试
# ------------------------------------------------------------
参数 说明
# ------------------------------------------------------------
-e 文件名 如果文件存在则为真
-r 文件名 如果文件存在且可读则为真
-w 文件名 如果文件存在且可写则为真
-x 文件名 如果文件存在且可执行则为真
-s 文件名 如果文件存在且至少有一个字符则为真
-d 文件名 如果文件存在且为目录则为真
-f 文件名 如果文件存在且为普通文件则为真
-c 文件名 如果文件存在且为字符型特殊文件则为真
-b 文件名 如果文件存在且为块特殊文件则为真
# ------------------------------------------------------------
cd /bin
if test -e ./bash; then
echo '文件已存在!'
else
echo '文件不存在!'
fi
# Shell 还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为: ! 最高, -a 次之, -o 最低。
cd /bin
if test -e ./notFile -o -e ./bash; then
echo '至少有一个文件存在!'
else
echo '两个文件都不存在'
fi
流程控制
- 如果 else 分支没有语句执行,就不要写这个 else
# if
if condition then
command1
command2
...
commandN
fi
# if else
if condition then
command1
command2
...
commandN
else
command
fi
# if else-if else
if condition1 then
command1
elif condition2 then
command2
else
commandN
fi
# for 循环
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
# while 语句
while condition
do
command
done
# 无限循环
# until 循环
# case ... esac
# break 命令
# continue 命令
函数
- 可以带 function fun() 定义,也可以直接 fun() 定义,不带任何参数。
- 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return 后跟数值 n(0-255).
- return 语句只能返回一个介于 0 到 255 之间的整数,而两个输入数字的和可能超过这个范围。要解决这个问题,您可以修改 return 语句,直接使用 echo 输出和而不是使用 return
- 函数返回值在调用该函数后通过 $? 来获得。
# 传参数
EXCUTE_DOCKER_TASK() {
echo -e $1
echo -e $2
}
EXCUTE_DOCKER_TASK 1 2
# 输出
1
2
function demoFun(){
echo "这是我的第二个 shell 函数!"
}
echo $?
function getbuildDir() {
echo 1;
}
value=$(getbuildDir);
echo "结果: ${value}";
函数参数
在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...
- $10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。
传递参数
# ------------------------------------------------------------
参数处理 说明
# ------------------------------------------------------------
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$- 显示Shell使用的当前选项,与set命令功能相同。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
# ------------------------------------------------------------
# 示例
echo "Shell 传递参数实例!";
echo "第一个参数为:$1";
echo "参数个数为:$#";
echo "传递的参数作为一个字符串显示:$*";
# 执行脚本
./test.sh 1 2 3
# $* 与 $@ 区别
echo "-- \$* 演示 ---"
for i in "$*"; do
echo $i
done
echo "-- \$@ 演示 ---"
for i in "$@"; do
echo $i
done
输入/输出重定向
文件包含
Shell 也可以包含外部脚本
# 方式一
. filename
. ./test.sh
# 方式二
source filename
source ./test.sh
操作系统命令
统一使用 $()来实现,例如current_dir=$(pwd),即可读取当前目录并赋值给变量
# 操作系统
# 文件操作
# 使用命令替换将 ls ./ -a 的输出存储到变量中
files=$(ls ./ -a);
echo "$files";
current_dir=$(pwd);
echo "${current_dir}";
互动式
# 用户输入
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
# Is this ok [y/N]:
read -r -p "请确认当前目录是否为ERP构建打包目录 [y/N]: " dir_confirm;
echo "${dir_confirm}";
# 获取构建打包目录
function getbuildDir() {
response_text="";
# 2. 交互式确认:循环直到获取有效输入(y/Y/n/N)
while true; do
# 显示提示并读取用户输入,存入变量 response
# -p:直接在命令行显示提示语;-r:禁止反斜杠转义(避免输入 \ 时出错)
read -r -p "当前构建目录是 ${OWN_TEST_DIR_PWD},请确认当前目录是否为ERP构建打包目录 [y/N]: " response;
# 3. 用 case 语句判断输入(比 if-elif 更简洁)
case "$response" in
# 接受 y 或 Y,或直接回车(空输入):执行“确认”逻辑
[yY]|"")
response_text="y";
break # 退出循环,结束交互
;;
# 接受 n 或 N:执行“取消”逻辑
[nN]|*)
break # 退出循环,结束交互
;;
esac
done
if [[ ! $response_text || $response_text != "y" ]]; then
warn "已退出当前构建打包进程 \n\n";
# 终止执行
exit -1;
fi
}
vue打包程序.sh
对比文件.sh
# /bin/sh ./init.sh
# 对比文件
RESULT=`diff /home/meta/Configure/shell/file/buid.json /home/meta/Configure/shell/file/package.json`
DEFAULT=""
if [ "${RESULT}" != "${DEFAULT}" ]
then
npm install
fi
node.sh
nginx.sh
# put /Users/ysun/project/server/docment/shell/example/nginx.sh /etc/init.d/
#!/bin/sh
if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then
/usr/local/webserver/nginx/sbin/nginx
fi
sleep 2
if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then
service keepalived stop
fi
docker-build.sh案例
#!/bin/bash
OWN_NODE_IMAGE_VERSION="node:22.15.0";
OWN_NODE_IMAGE_NAME="node-docker-build";
# 项目存放目录
OWN_DOCKER_WWW="/home/list";
own_dokcer_www_dir="";
own_dokcer_www_node_modules_dir="";
# 主函数
function ownDockerManager() {
echo -e "\n\n\n\n\n\n\n\n\n\n";
success "开始进入docker容器打包构建流程";
info "正在启动Docker容器...";
info "基础要求: node镜像版本: ${OWN_NODE_IMAGE_VERSION} node镜像名称: ${OWN_NODE_IMAGE_NAME}";
# 检查是否存在正在进行的任务
# 检查docker环境
ownDockerCheckEnv;
# 检查node容器
ownDockerCheckNode;
# 查看docker环境中node环境
ownDcokerFindNodeEnv;
# 打包构建
buildManage;
success "完成docker容器打包构建流程";
echo -e "\n\n";
sleep 1s;
}
# 打包构建
function buildManage() {
echo -e "\n\n";
echo -e "\033[0;33m\$service_dir\033[0m: ${service_dir}";
echo -e "\033[0;33m\$main_repo_dir\033[0m: ${main_repo_dir}";
echo -e "\033[0;33m\$tmp_dir\033[0m: ${tmp_dir}";
echo -e "\033[0;33m\$new_name\033[0m: ${new_name}";
echo -e "\033[0;33m\$clear_node_modules_dir\033[0m: ${clear_node_modules_dir}";
echo -e "\033[0;33m\$ares_env\033[0m: ${ares_env}";
echo -e "\033[0;33m\$region\033[0m: ${region}";
echo -e "\033[0;33m\$repo_dir\033[0m: ${repo_dir}";
echo -e "\033[0;33m\$common_dir\033[0m: ${common_dir}";
echo -e "\033[0;33m\$common_node_modules_dir\033[0m: ${common_node_modules_dir}";
echo -e "\033[0;33m\$repo_node_modules_dir\033[0m: ${repo_node_modules_dir}";
echo -e "\033[0;33m\$env_file\033[0m: ${env_file}";
echo -e "\n";
own_dokcer_www_dir="${OWN_DOCKER_WWW}/${main_repo_dir}";
own_dokcer_www_node_modules_dir="${own_dokcer_www_dir}/node_modules";
echo -e "\033[0;33m\$OWN_DOCKER_WWW\033[0m: $OWN_DOCKER_WWW";
echo -e "\033[0;33m\$own_dokcer_www_dir\033[0m: ${own_dokcer_www_dir}";
echo -e "\033[0;33m\$own_dokcer_www_node_modules_dir\033[0m: ${own_dokcer_www_node_modules_dir}";
cmd_logger="在 node镜像:${OWN_NODE_IMAGE_NAME} 中执行指令";
# 清除历史文件
warn "${cmd_logger} rm -rf $own_dokcer_www_dir";
ownDockerExcuteTask "rm -rf $own_dokcer_www_dir";
warn "已清空 $own_dokcer_www_dir 目录";
# 拷贝项目
warn "${cmd_logger} mkdir -p $OWN_DOCKER_WWW";
ownDockerExcuteTask "mkdir -p $OWN_DOCKER_WWW";
ownDockerExcuteTask "cd $OWN_DOCKER_WWW && pwd && ls ./ -a";
warn "docker cp $repo_dir $OWN_NODE_IMAGE_NAME:$OWN_DOCKER_WWW";
docker cp $repo_dir $OWN_NODE_IMAGE_NAME:$OWN_DOCKER_WWW;
ownDockerExcuteTask "cd $OWN_DOCKER_WWW && pwd && ls ./ -a && cat ./public/version.json";
### 判断是否使用缓存的node_modules,缓存时编译会更快,但可能有依赖错误
warn "${cmd_logger} rm -rf $own_dokcer_www_node_modules_dir";
ownDockerExcuteTask "rm -rf $own_dokcer_www_node_modules_dir";
if [ "$clear_node_modules_dir" == "y" ]; then
info "清除node_modules历史数据,重新拉取最新依赖包";
else
info "继续使用node_modules历史数据";
warn "docker cp ${repo_node_modules_dir} ${OWN_NODE_IMAGE_NAME}:${own_dokcer_www_dir}";
docker cp ${repo_node_modules_dir} ${OWN_NODE_IMAGE_NAME}:${own_dokcer_www_dir};
fi
ownDockerExcuteTask "cd $own_dokcer_www_dir && pwd && ls ./ -a";
# 添加安全目录
ownDockerExcuteTask "git config --global --add safe.directory /home/list/erp_fe";
# 拉取依赖包,如果存在缓存,则不请求远程,从本地获取
ownDockerExcuteTask "cd ${own_dokcer_www_dir} && npm config set registry https://registry.npmmirror.com && yarn install && yarn add terser";
# 海外
if [ "$region" == "global" ]; then
# 海外线上
if [ "$ares_env" == "online" ]; then
ownDockerExcuteTask "cd ${own_dokcer_www_dir} && npm run build:global";
else
# 海外test
ownDockerExcuteTask "cd ${own_dokcer_www_dir} && npm run build:test:global";
fi
else
# 国内线上
if [ "$ares_env" == "online" ]; then
ownDockerExcuteTask "cd ${own_dokcer_www_dir} && npm run build";
else
# 国内test
ownDockerExcuteTask "cd ${own_dokcer_www_dir} && npm run build:test";
fi
fi
####
### 判断编译生成目标文件后,才进行下一步
####
dist_index="${own_dokcer_www_dir}/dist/index.html";
if ! docker exec ${OWN_NODE_IMAGE_NAME} test -e ${dist_index}; then
error "文件 ${dist_index} 不存在,请检查具体编译问题";
exit -1;
fi
success_dist=$(ownDockerExcuteTask "grep '/static/js/index' $dist_index");
# 未生成目标文件
if [ "$success_dist" == "" ]; then
error "编译出错了,请检查依赖是否正确";
exit -1;
else
success "编译成功, 进行发布中";
fi
# 查看文件夹
ownDockerExcuteTask "cd ${own_dokcer_www_dir} && pwd && ls ./ -a && cat ./public/version.json";
# 把own_dokcer_www_node_modules_dir依赖包复制到$repo_node_modules_dir
warn "docker cp ${OWN_NODE_IMAGE_NAME}:${own_dokcer_www_node_modules_dir} ${repo_node_modules_dir}";
docker cp ${OWN_NODE_IMAGE_NAME}:${own_dokcer_www_node_modules_dir} ${repo_node_modules_dir};
# 把dist复制到 $repo_dir
warn "docker cp ${OWN_NODE_IMAGE_NAME}:${own_dokcer_www_dir}/dist ${repo_dir}";
docker cp ${OWN_NODE_IMAGE_NAME}:${own_dokcer_www_dir}/dist ${repo_dir};
}
# 查看docker环境中node环境
function ownDcokerFindNodeEnv() {
info "当前脚本所在目录: $(pwd)";
echo -e "\n\n";
success "已进入docker环境";
ownDockerExcuteTask "pwd";
ownDockerExcuteTask "ls ./ -a";
node_version=$(ownDockerExcuteTask "node -v");
npm_version=$(ownDockerExcuteTask "npm -v");
info "node版本号:$node_version";
info "npm版本号:$npm_version";
docker cp /etc/localtime ${OWN_NODE_IMAGE_NAME}:/etc/localtime;
}
# 检查docker环境
function ownDockerCheckEnv() {
info "开始检查docker环境是否正常";
# 版本信息
if docker_version=$(docker -v 2>/dev/null); then
info "docker版本号: $docker_version";
else
warn "docker未安装或执行异常,正在紧急修复中...";
ownDockerInstall;
fi
}
# 安装配置docker环境
function ownDockerInstall() {
error "docker暂时不提供自动安装配置";
exit -1;
}
# 检查node容器
function ownDockerCheckNode() {
info "正在检查 node镜像:${OWN_NODE_IMAGE_NAME} 是否已经存在...";
docker ps -a;
# 检查容器是否存在(包含停止状态)
if ! docker inspect "${OWN_NODE_IMAGE_NAME}" &> /dev/null; then
warn "node镜像:${OWN_NODE_IMAGE_NAME} 不存在,正在紧急修复中...";
ownDockerInstallNodeImage;
else
success "node镜像:${OWN_NODE_IMAGE_NAME} 已存在"
fi
# 检查容器是否正在运行
info "正在检查node镜像: ${OWN_NODE_IMAGE_NAME} 是否正常运行...";
if [ "$(docker inspect -f '{{.State.Running}}' "${OWN_NODE_IMAGE_NAME}")" != "true" ]; then
error "node镜像:${OWN_NODE_IMAGE_NAME} 未运行";
ownDockerManageNodeImage;
else
success "node镜像: ${OWN_NODE_IMAGE_NAME} 正常运行";
fi
}
# 安装配置node镜像
function ownDockerInstallNodeImage() {
# 检查镜像是否存在
if docker images --format "{{.Repository}}:{{.Tag}}" | grep -q "^${OWN_NODE_IMAGE_VERSION}$"; then
success "node镜像:${OWN_NODE_IMAGE_VERSION} 已存在于本地,正在启动中...";
else
warn "node镜像:${OWN_NODE_IMAGE_VERSION} 在本地未找到,正在从远程库下载中...";
# 拉取版本镜像
docker pull $OWN_NODE_IMAGE_VERSION;
success "已下载完成 node镜像:${OWN_NODE_IMAGE_VERSION},正在安装中...";
fi
# 激活运行,但不进入
docker run -td --name $OWN_NODE_IMAGE_NAME $OWN_NODE_IMAGE_VERSION;
success "已安装配置完成 node镜像:${OWN_NODE_IMAGE_NAME},处于激活状态,可以正常使用";
}
# 启动node镜像
function ownDockerManageNodeImage() {
info "node镜像:${OWN_NODE_IMAGE_VERSION} 正在启动中...";
docker start $OWN_NODE_IMAGE_NAME;
sleep 1s;
if [ "$(docker inspect -f '{{.State.Running}}' "${OWN_NODE_IMAGE_NAME}")" != "true" ]; then
error "node镜像:${OWN_NODE_IMAGE_NAME} 启动失败,已退出,请人工介入排查";
exit -1;
fi
success "node镜像:${OWN_NODE_IMAGE_VERSION} 已重启,可以正常运行";
}
# 执行docker任务
function ownDockerExcuteTask() {
task_cmd=$1
echo -e "\n";
docker exec -it "${OWN_NODE_IMAGE_NAME}" /bin/bash -c "${task_cmd}";
}
# 日志
OWN_DOCKER_COLOR_RED='\033[0;31m' # 红色
OWN_DOCKER_COLOR_GREEN='\033[0;32m' # 绿色
OWN_DOCKER_COLOR_YELLOW='\033[0;33m' # 黄色
OWN_DOCKER_COLOR_BLUE='\033[0;34m' # 蓝色
OWN_DOCKER_COLOR_BOLD_RED='\033[1;31m' # 红色加粗
OWN_DOCKER_COLOR_NC='\033[0m' # 重置颜色
# 错误日志
function error() {
echo -e "\n${OWN_DOCKER_COLOR_RED}[错误] $(date +"%Y-%m-%d %H:%M.%S") ${OWN_DOCKER_COLOR_NC} $1";
}
# 警告日志
function warn() {
echo -e "\n${OWN_DOCKER_COLOR_YELLOW}[警告] $(date +"%Y-%m-%d %H:%M.%S") ${OWN_DOCKER_COLOR_NC} $1";
}
# 成功
function success() {
echo -e "\n${OWN_DOCKER_COLOR_GREEN}[成功] $(date +"%Y-%m-%d %H:%M.%S") ${OWN_DOCKER_COLOR_NC} $1";
}
# 信息日志
function info() {
echo -e "\n[信息] $(date +"%Y-%m-%d %H:%M.%S") $1";
}
# 调试日志
function debug() {
echo -e "\n${OWN_DOCKER_COLOR_BLUE}[调试] $(date +"%Y-%m-%d %H:%M.%S") ${OWN_DOCKER_COLOR_NC} $1";
}
CentOS7
官网:https://www.centos.org/ 下载:https://www.centos.org/download/ Aliyun镜像:https://mirrors.aliyun.com/centos/8/isos/x86_64/
perf性能分析工具
perf是一款Linux性能分析工具。
JSLinux
由程序员Fabrice Bellard写了一段Javascript在Web浏览器中启动Linux。这个模似器完全由Javascript写成CPU仿真器使用的是QEMU(接近于原古的486)。