E103-W20添加WM8978声卡前言在很久之前我看到MT7628AN有i2s接口,于是买了一块WM8978G模块.但因为某些原因,该功能一直没有实现,在国庆期间闲来无事,进行了一番调试,在此记录.设备环境模组/开发板:E103-W20路由器,具体参考我的工程:E103-W20路由器音频模组:W8978G模组,淘宝极客科技店铺购买系统:OpenWrt 21.02硬件连接WM8978 MT2628 DAT（I2C_SDI/eX_sd） I2C_SDI MCK（I2S_MCLK） I2S_MCLK(refclk) SCK（I2S_SCLK/BCLK） I2S_SCK SDB（I2C_SDO/SD） I2C_SDO FSA（I2S_LRC/WS） I2S_WS SCL（I2C_SCL） I2C_SCL SDA（I2C_SDA） I2C_SDA请注意,MT7628没有I2S_MCLK引脚,这里用的是MT7628的REF_CLKO引脚来代替MCLK.MT7628的REF_CLKO引脚默认功能是12Mhz参考时钟输出.设备树实现// 请在'/'根节点添加以下内容 sound { compatible = "simple-audio-card"; simple-audio-card,name = "WM8978-Sound-Card"; simple-audio-card,format = "i2s"; simple-audio-card,bitclock-master = <&codec_dai>; simple-audio-card,frame-master = <&codec_dai>; simple-audio-card,mclk-fs = <256>; cpu_dai: simple-audio-card,cpu { sound-dai = <&i2s>; }; codec_dai: simple-audio-card,codec { sound-dai = <&wm8978>; }; }; //在根节点外添加或者修改以下内容 &i2c { status = "okay"; clock-frequency = <400000>; wm8978: wm8978@1a { status = "okay"; compatible = "wlf,wm8978"; reg = <0x1a>; #sound-dai-cells = <0>; }; }; &i2s { status = "okay"; #sound-dai-cells = <0>; pinctrl-names = "default"; pinctrl-0 = <&i2s_pins>, <&refclk_pins>; }; 项目编译因为Openwrt没有提供kmod-soc-wm8978之类的包,所以需要我们在内核中配置.使用make kernel_menuconfig打开内核配置请参考以下配置来打开WM8978支持.在这里,我配置的是把WM8978编译成内核模块方便调试,实际可以编译到内核里.Device Drivers -> I2C support -> <*>I2C Support Device Drivers -> <*>Sound Card Support -> <*>Advanced Linux Sound Architecture -> <*> Sound hardware support [*] Enable OSS Emulation [*] MIPS sound devices ---- <*> ALSA for SoC audio support ---> <*> SoC Audio (I2S protocol) for Ralink SoC <*> ASoC Simple sound card support CODEC drivers ---> <M> Wolfson Microelectronics WM8978 codec使用make menuconfig打开Openwrt配置请参考以下配置,kmod-usb-audio用于外接usb声卡,可以选择不编译.Kernel modules -> I2C support -> -*- kmod-i2c-core <*> kmod-i2c-mt7628 Kernel modules -> Sound Support -> -*- kmod-sound-core -*- kmod-ac97 <*> kmod-sound-mt7620 -*- kmod-sound-soc-core <*> kmod-usb-audio Sound -> <*> alsa-utils使用make -j32来编译整个系统.编译完成之后,固件位于以下目录:Openwrt-21.02/bin/targets/ramips/mt76x8/openwrt-ramips-mt76x8-hilink_hlk-7628n-squashfs-sysupgrade.bin请在刷写完成新固件之后进行下一步.调试如果一切顺利,你可以在dmesg日志里看到以下被标注出来的输出:root@LAPTOP-BQECF4:~# dmesg | grep -E "(i2s|wm89)" [ 0.875233] rt2880-pinmux pinctrl: i2s is already enabled [ 0.898742] rt2880-pinmux pinctrl: i2s is already enabled [ 4.234765] rt2880-pinmux pinctrl: i2s is already enabled [ 4.400733] rt2880-pinmux pinctrl: i2s is already enabled [ 4.576246] rt2880-pinmux pinctrl: i2s is already enabled [ 4.632818] rt2880-pinmux pinctrl: i2s is already enabled [ 5.427167] rt2880-pinmux pinctrl: i2s is already enabled [ 16.204231] rt2880-pinmux pinctrl: i2s is already enabled *** [ 16.226524] ralink-i2s 10000a00.i2s: mclk 480MHz //这一行 [ 16.311999] i2c i2c-0: of_i2c: register /palmbus@10000000/i2c@900/wm8978@1a [ 16.312146] i2c i2c-0: client [wm8978] registered with bus id 0-001a [ 16.352430] i2c-core: driver [wm8960] registered [ 728.571579] wm8978 0-001a: probe [ 728.572242] i2c-core: driver [wm8978] registered *** [ 728.590344] asoc-simple-card sound: wm8978-hifi <-> 10000a00.i2s mapping ok //这一行 使用aplay -l列出声卡来检验是否存在wm8978声卡root@LAPTOP-BQECF4:~# aplay -l **** List of PLAYBACK Hardware Devices **** card 0: WM8978SoundCard [WM8978-Sound-Card], device 0: ralink-i2s-wm8978-hifi wm8978-hifi-0 [ralink-i2s-wm8978-hifi wm8978-hifi-0] Subdevices: 1/1 Subdevice #0: subdevice #0 可以看到存在WM8978声卡.使用alsamixer来进行图形化的音频选项修改.使用F6选择声卡,M改变开关,ESC退出使用aplay播放测试音频,使用-Dhw:CardID,DeviceID来选择指定声卡,在上面的log可以看到这块声卡cardID为0,DeviceID为0.aplay -Dhw:0,0 -vv /tmp/test.wav,这将会播放/tmp/test.wav,请把这个改成你自己的路径.在耳机或者喇叭处聆听是否有声音输出.问题首先是dts的问题,这里折腾了很久,被ralink-i2s 10000a00.i2s: mclk 480MHz这行日志忽悠了,最后通过示波器检验refclk引脚的时钟输出确认refclk的时钟输出是12Mhz.第二个就是设备树里的widget和route部件,如果写了就会在日志里报错没有sink和source的问题,最后把这两个去掉,让系统自动配置.第三个就是在我这块WM8978模块上,只有微弱的声音输出,到现在没有确定是模块的问题还是寄存器数值的问题.寄存器数值可以通过以下命令查看:cat /sys/kernel/debug/regmap/0-001a/registers.请注意,由于WM8978在I2C模式下是只写的,寄存器不能读取,所以这里查看的是regmap的写入缓存鉴于暂时没有能力换一块wm8978,故目前止步于此.总结与收获调试很费时间,但是借助D指导(DeepSeek)和不懈搜索,也是感悟良多.几乎把alsa的框架源码和wm8978的源码分析了一整遍.也参考wm8978的数据手册分析寄存器.通过alsamixer的混音板来反向分析代码和寄存器,大致了解了工作原理.等以后有时间争取完工.补充说明2025.10.05使用stm32F407 USB to I2S方式测试wm8978，发现声音也是很小。可能是wm8978坏了的问题。
VSCode VSIX插件离线下载前言在树莓派上安装code-server，新版本的C/C++插件提示不受支持。找了很多文章才实现离线下载旧版本插件，故此记录。注意此方法只适用于单个插件下载，对于插件包并不适用。如果无法下载插件，可以尝试到插件的GitHub项目中寻找发行版。链接格式已知VSIX下载链接格式如下：https://marketplace.visualstudio.com/_apis/public/gallery/publishers/{发布者}/vsextensions/{插件名}/{版本号}/vspackage https://marketplace.visualstudio.com/_apis/public/gallery/publishers/{发布者}/vsextensions/{插件名}?targetPlatform={platform} https://marketplace.visualstudio.com/_apis/public/gallery/publishers/{发布者}/vsextensions/{插件名}/{版本号}/vspackage?targetPlatform={platform}发布者与插件名More Info Version 1.26.3 Released on 2016/3/30 09:27:12 Last updated 2025/6/26 03:02:16 Publisher Microsoft Unique Identifier ms-vscode.cpptools # 发布者.插件名 Report Report a concern找到插件主页右下角的More Info栏，定位到Unique Identifier其中，发布者与插件名依据.分隔Platform分类目前有以下平台win32-x64: Windows 64-bitwin32-ia32: Windows 32-bitwin32-arm64: Windows ARM64darwin-x64: macOS Inteldarwin-arm64: macOS Apple Siliconlinux-x64: Linux 64-bitlinux-arm64: Linux ARM64alpine-x64: Alpine Linux版本号一般而言，看插件主页的Version History即可，上古版本建议去github看看。示例：C/C++插件发布者：ms-vscode插件名：cpptools版本：1.26.3平台：win32-x64https://marketplace.visualstudio.com/_apis/public/gallery/publishers/ms-vscode/vsextensions/cpptools/1.26.3/vspackage https://marketplace.visualstudio.com/_apis/public/gallery/publishers/ms-vscode/vsextensions/cpptools?targetPlatform=win32-x64 https://marketplace.visualstudio.com/_apis/public/gallery/publishers/ms-vscode/vsextensions/cpptools/1.26.3/vspackage?targetPlatform=win32-x64
Sqxy宿舍电费微信推送前言宿舍电费只能使用支付宝完美校园小程序查询，还要忍受一堆广告。因此这里也是直接抓包，获得了电费查询的url。通过curl请求、crontab再配合微信测试号实现定时推送。软件工具curl这里只要安装了curl即可。使用方法获取微信测试号 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login获取微信AppID、AppSecert创建推送模板，获取Template_ID调用access_token接口获取Token调用电费接口获取剩余电费调用测试号推送接口推送电费数据将脚本放入Openwrt，使用Crontab定时推送模板微信测试号消息创建模板今天是：{{date.DATA}} 您的宿舍号是：{{roomno.DATA}} 当前剩余电费：{{electricities.DATA}}微信测试号消息推送json模板{ "touser": "被推送的用户id，用户关注测试号后获取", "template_id": "你的template_id,消息模板创建成功后获取", "url": "http://weixin.qq.com/download", "data": { "date": { "value": "2025年7月3日" }, "roomno": { "value": "30#2001" }, "electricities": { "value": "12.23度" } } }完美校园电费请求参数json模板{ "timestamp": "2025-03-02 17:48:02", "method": "samllProgramGetRoomState", "bizcontent": "{\"payproid\":953,\"schoolcode\":\"1402\",\"roomverify\":\"2-11--2-6005\",\"businesstype\":2}", "sourceId": 1 }完美校园电费返回值json模板{ "businessData": { "description": "剩余电量", "quantity": "97.55", "quantityunit": "度" }, "returncode": "SUCCESS", "returnmsg": "获取成功", "subCode": null, "subMsg": null }测试结果附件shell脚本源码#!/bin/bash ### configs # appID APPID='你的APPID' # appsecret APPSECRET='你的APPSECRET' # template_id TEMPLATE_ID='你的TEMPLATE_ID' # access_token TOKEN="" # followers FOLLOWERS=( '用户token1' # 用户1 '用户token2' # 用户2 ) ### headers # user-agent USER_AGENT="User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35" # accept ACCEPT="accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" # content type CONTENT_TYPE="Content-Type: application/json" ### ### date # date formated # current date CUR_DATE=$(date '+%Y年%m月%d日') # Room No. ROOMNO='你的宿舍号' # electricities ELECTRICITIES="" # json data JSON_DATA="" # template url TEMPLATE_URL="http://weixin.qq.com/download" ### ### urls # get token GET_TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token" GET_TOKEN_URL_PARAM="grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}" ### functions # get token get_token() { local RET=$(curl -s -H "${USER_AGENT}" -H "${ACCEPT}" -d "${GET_TOKEN_URL_PARAM}" $GET_TOKEN_URL) # unset TOKEN TOKEN=$(echo $RET | cut -d : -f 2 | cut -d , -f 1 | cut -d \" -f 2) return 0 } # push Message push_message() { get_token get_electricities # push message JSON_PATH="./data.json" PUSH_MESSAGE_URL="https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${TOKEN}" for ((i = 0; i < ${#FOLLOWERS[@]}; i++)); do local user=${FOLLOWERS[$i]} encode_data_json ${user} local RET=$(curl -s -H "${USER_AGENT}" -H "${ACCEPT}" -H "${CONTENT_TYPE}" -d "${JSON_DATA}" $PUSH_MESSAGE_URL) # local RET=$(curl -H $USER_AGENT -H $ACCEPT -H $CONTENT_TYPE -d $JSON_PATH $PUSH_MESSAGE_URL) echo $RET done } # 构造模板json数据 encode_data_json() { # unset JSON_DATA JSON_DATA="{\"touser\": \"$1\",\"template_id\": \"${TEMPLATE_ID}\",\"url\": \"${TEMPLATE_URL}\",\"data\": {\"date\": {\"value\": \"${CUR_DATE}\"},\"roomno\": {\"value\": \"${ROOMNO}\"},\"electricities\": {\"value\": \"${ELECTRICITIES}\"}}}" } # get electricities get_electricities() { local RET=$( curl -s -X POST 'https://cloudpaygateway.59wanmei.com:8087/paygateway/smallpaygateway/trade' \ -H 'Origin: https://cloudpaygateway.59wanmei.com:8087' \ -H 'Accept: application/json, text/plain, */*' \ -H 'X-Requested-With: com.eg.android.AlipayGphone' \ -H 'Referer: https://cloudpaygateway.59wanmei.com:8087/pay/index.html?token=你的token&_timestamp=1740900078698&customerId=1402' \ -H 'Sec-Fetch-Site: same-origin' \ -H 'Sec-Fetch-Dest: empty' \ -H 'Accept-Encoding: gzip' \ -H 'Sec-Fetch-Mode: cors' \ -H 'x-mass-tappid: 2019030163398604' \ -H 'Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7' \ -H 'Content-Type: application/json;charset=UTF-8' \ -H 'Content-Length: 193' \ -H 'User-Agent: Mozilla/5.0 (Linux; Android 14; OPD2201 Build/UKQ1.230924.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/105.0.5195.148 MYWeb/0.11.0.250212163947 UWS/3.22.2.9999 UCBS/3.22.2.9999_220000000000 Mobile Safari/537.36 NebulaSDK/1.8.100112 Nebula AlipayDefined(nt:WIFI,ws:560|0|2.5,ac:sp) AliApp(AP/10.7.0.8000) AlipayClient/10.7.0.8000 Language/zh-Hans useStatusBar/true isConcaveScreen/false Region/CNAriver/1.0.0 MiniProgram APXWebView DTN/2.0' \ -H 'Connection: Keep-Alive' \ -H 'Host: cloudpaygateway.59wanmei.com:8087' \ --data '{"timestamp":"2025-03-02 15:21:20","method":"samllProgramGetRoomState","bizcontent":"{\"payproid\":953,\"schoolcode\":\"1402\",\"roomverify\":\"2-11--6-6035\",\"businesstype\":2}","sourceId":1}' ) # unset ELECTRICITIES ELECTRICITIES=$(echo $RET | cut -d : -f 4 | cut -d , -f 1 | cut -d \" -f 2) if [ $(printf "%.0f" ${ELECTRICITIES}) -gt "10" ]; then ELECTRICITIES+="度，电费大大滴有" else ELECTRICITIES+="度，你滴，快充电费~" fi } # main function push_message
[TOC]CentOS/RHEL命令学习笔记Linux命令软件包与软件源软件的安装方式yum 软件包管理器底层是rpm自动解决依赖问题安装完成会自动清理软件包文缓存安装分为远程安装和本地安装本地yum源 file://本地yum源路径远程yum源 http://xxx ftp://xxx用法：yum [参数] 包名 参数介绍： 常用指令参数组合： yum install 软件名 # 安装软件包 yum repolist # 查询yum源信息 yum install epel-release # 增加拓展源 yum clean all # 清除缓存 # 若替换了yum源 系统默认的缓存内容不会变化, # 找不到新替换的yum源,此时会报错 需要及时清理缓存 yum makecache # 加载缓存 ls -al /etc/yum.repos.d/ # 查看可使用的yum源 yum provides 命令 # 查看命令属于哪个软件,即使本地不存在的软件指令,yum也可以寻找 yum list # 查看系统已经安装好的软件和没有安装的软件(源里存在即可查找到) yum -y reinstall 软件名 # 重装 yum remove 软件名 # 卸载 yum erase 软件名 # 清除软件配置文件 示例： 1. yum安装mysql yum install mysqlrpm 软件包管理器，较少使用无法自动解决依赖关系，需要手动解决适用于依赖较少或已知依赖关系的情况rpm软件包名称： 软件名称 版本号(主版本 次版本 修订号) 操作系统 ---- 90%的命名规律用法：rpm [参数] 包名 - 资源路径可以是本地路径，也可以是网络链接 1. 查找rpm包 2. wget 网络资源路径 - wget需要手动安装 3. 使用 rpm -ivh xxx.rpm 从本地安装 4. 使用 rpm -ivh url链接 从网络安装（与上面的步骤二选一） 参数介绍： -i 安装 -v 显示安装信息 -h 显示安装进度 -U 安装时检测安装包版本是否最新，如不是则先升级再安装 -a 查看所有已安装的软件包 -q 查询所有已安装的软件包 -l 显示软件包的文件列表 -e 卸载指定的软件包 -f 软件包中的文件 常用指令参数组合： -ivh 安装指定软件包并显示进度 -qa 查询所有已安装的软件包 -qi 查询软件包的安装信息 示例： 5. 查询指定软件包 rpm -qa | grep 包名 6. 显示软件包的安装文件 rpm -ql 包名 7. 查询某个文件属于哪个软件包 rpm -qf 软件安装路径 # 只能查看已安装好的软件包 rpm软件包查找网站： - rpm find https://www.rpmfind.net/ - pkgs.org https://pkgs.org/源码安装一个软件想要在linux中运行,必须是二进制文件。 因此当我们拿到软件源码以后,需要将它编译(翻译)为二进制文件,才能在linux中运行。 源码包在编译时需要使用Linux系统的编译器. 通常源码包都是用C语言开发的[这是因为C语言是Linux最标准的程序语言,效率高]。 Linux中C语言编译器叫做 gcc. 利用gcc 可以把C语言变成可执行的二进制文件 源码安装的优点 - 编译安装的过程,可以设定参数[例如 安装路径 日志路径....], - 按照需求增加功能,并且可以指定安装的版本,灵活性比较大。 获取源码包 - 研发部自研 - 官方网站,获取软件包CentOS7换源/etc/yum.repos.d 源的存放位置http://mirrors.aliyun.com/repo/Centos-7.repo Ali Mirrorhttps://mirrors.163.com/.help/CentOS7-Base-163.repo wangyi Mirror备份源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup下载Ali Mirror源 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo更新镜像源 yum clean all # 清理缓存 yum makecache # 重新建立缓存防火墙防火墙 防范一些网络攻击。有软件防火墙、硬件防火墙之分区域区域策略trusted 信任区允许所有数据包home 家庭区拒绝流入的流量，除非与流出的流量相关。允许ssh mdns ippclient amba-client dhcpv6-client服务通过internal 内部区等同于homework 工作区拒绝流入的流量，除非与流出的流量相关。允许ssh dhcpv6-client服务通过public 公共区域拒绝流入的流量，除非与流出的流量相关。允许ssh dhcpv6-client服务通过external 外部区域拒绝流入的流量，除非与流出的流量相关。允许ssh服务通过dmz 隔离区域/非军事区域拒绝流入的流量，除非与流出的流量相关。允许ssh服务通过block 限制区域拒绝流入的流量，除非与流出的流量相关。非法流量采取拒绝操作，有响应消息drop 丢弃区域拒绝流入的流量，除非与流出的流量相关。非法流量采取拒绝操作，无响应消息拒绝流入的流量，除非与流出的流量相关。例如下载东西，需要先访问对方服务器，即流出。 此时对方会发送回复，即流入。此时就是流入与流出相关。 如果是对方发送一个请求，比如你的多年不联系的微信好友突然找你借钱一样，很突然，而且事先没有联系。这种就是只有流入的流量。 响应消息。即朋友突然找你借钱，你不借，跟他说没钱。这种就是拒绝操作，有响应消息。 如果朋友突然找你借钱，你假装看不见也不借给他。这种就是拒绝操作，无响应消息。 区域管理firewall-cmd 防火墙管理工具，默认是临时操作用法：参数介绍：--get-default-zone 查看当前默认区域 --get-zones 查看所有区域 --list-all 查看当前区域配置 --list-all-zones 查看所有区域配置 --permanent 使操作永久生效 --reload 重新加载配置，相当于 `systemctl reload firewall` --zone=区域 指定区域 --add-service=服务名 指定服务 --remove-service=服务名 移除服务 --add-port=端口号/协议 添加指定协议上的端口 --remove-port=端口号/协议 移除指定协议上的端口 配置详情： [root@mkirin ~]# firewall-cmd --list-all public (active) target: default # 没有指定特定的目标规则集，可能是使用默认的规则集。 icmp-block-inversion: no # 不反转 ICMP 阻塞规则，即不对 ICMP 进行特殊处理。 interfaces: ens160 # 规则应用于 ens160 网络接口。 sources: # services: dhcpv6-client ssh # 允许通过防火墙的流量服务包括 SSH 和 DHCPv6 客户端。 ports: # 没有特定端口被指定，这可能意味着允许所有端口的流量通过。 protocols: # 没有指定特定的协议，这可能意味着允许所有协议的流量通过。 masquerade: no # 不对流量进行伪装，即不修改数据包的源地址。 forward-ports: # 没有指定端口转发规则，这可能意味着不进行端口转发。 source-ports: # 没有指定源端口规则，这可能意味着允许所有源端口的流量通过。 icmp-blocks: # 没有指定 ICMP 阻塞规则，这可能意味着 ICMP 流量不受阻碍。 rich rules: # 没有提供详细的规则，通常用于指定更复杂的防火墙规则防火墙放行添加服务方式服务需必须存储在/usr/lib/firewalld/services目录中方法：firewall-cmd --zone=区域 --add-service=服务名示例允许ftp通过防火墙 firewall-cmd --zone=public --add-service=ftp禁止ftp通过防火墙 firewall-cmd --zone=public --remove-service=ftp永久允许ftp通过防火墙 firewall-cmd --permanent --zone=public --add-service=ftp添加端口方式方法：firewall-cmd --zone=区域 --add-port=端口号/协议示例允许tcp的80端口通过防火墙 firewall-cmd --zone=public --add-port=80/tcp禁止tcp的80端口通过防火墙 firewall-cmd --zone=public --remove-port=80/tcp允许udp的80端口通过防火墙 firewall-cmd --zone=public --add-port=80/udp禁止udp的80端口通过防火墙 firewall-cmd --zone=public --remove-port=80/udp防火墙开关查看防火墙状态 systemctl status firewalld开启防火墙 systemctl start firewalld关闭防火墙状态 systemctl stop firewalld防火墙开机自启 systemctl enable firewalld关闭防火墙开机自启（永久关闭防火墙） systemctl disable firewalldSelinux/etc/sysconfig/selinux selinux配置文件查看selinux是否运行getenforce临时设置selinux状态：0：关闭 1：开启setenforce 0永久关闭selinuxvi /etc/sysconfig/selinux找到SELinux=行将其改为SELINUX=disabled保存配置文件，重启生效进程管理进程： - 进程是已经启动的可执行程序的运行实例。 - 是程序的运行过程。 - 动态的,有生命周期以及运行状态 查看进程静态查看进程ps 进程查看指令用法：ps [参数] 参数介绍 a 只能查看系统里面运行的所有终端进程 u 显示进程拥有者 x 显示系统内所有进程S f 显示进程之间的父子关系 -e 显示所有进程 -f 展示完整格式 -l 长格式展示STAT 进程状态(了解) ? 表示没有占用终端 R 运行 S 可中断睡眠 sleep D 不可中断睡眠 T 停止的进程 Z 僵尸进程 X 死掉的进程 Sl 以线程的方式运行 Ss s进程的领导者，也叫父进程 R+ +表示进程组 S< 优先级较高的进程 SN N优先级较低的进程 # 僵尸进程 表示进程已经退出,但它的父进程还没有回收子进程占用的资源。 短暂的僵尸状态通常不必理会,但进程如果长时间处于僵尸状态,就应该引起注意，可能是引用程序没有正常处理子进程的退出。 # S 可中断睡眠 Sleep ---- 类似于挂起，等待接受socket链接或者一些信号重新被唤起 # D 不可中断睡眠 --- 不可被打断，表示进程正在和硬件进行交互，为了保护进程数据和硬件数据一致,系统不允许其他进程中断这个过程。 进程长时间处于不可中断状态,通常表示系统的IO(内存与磁盘的交互)性能有问题 # 主进程和工作进程(子进程)： 主进程的主要作用是读取和评估配置文件,以及维护工作进程。 工作进程用于执行请求。动态查看进程top 动态展示信息,三秒刷新一次用法：top 内置命令介绍： h 帮助 > 往下翻页 < 往上翻页 M 按照内存占用排序 P 按照cpu占用排序 q 退出 z 彩色展示 示例：查看单个进程的PIDps -ef | grep '进程名或PID'示例： 1. 查看nginx的进程PID ps -ef | grep 'nginx'查看pid文件 1. 查看httpd的PID cat /var/run/httpd/http.pid # 会输出pid，但是PID每次开启进程,都会变化 2. 查看nginx的pid cat /usr/local/nginx/logs/nginx.pid # 获取pid的效率比 ps aux 效率高管理进程杀死进程kill用法：kill [参数] pid 参数介绍： -l 查看所有信号参数 常见信号： -1 重新加载进程或者重新加载配置文件 -9 强制杀死 -15 正常杀死(这个参数可以省略) -18 激活线程 -19 挂起线程 示例：pkill用法：pkill [参数] pid 参数介绍： 示例：查看端口占用lsof 查看端口占用情况，与ps类似，配合grep使用安装方法：yum install lsof用法：lsof [参数] 参数介绍： 示例： 1. 查看80端口占用 lsof -i :80netstat 查看网络进程和正在监听的端口，配合grep使用安装方法：yum install net-tools用法：netstat [参数] 参数介绍： -l 只显示正在被监听的端口 -p 显示进程的名称和 pid -n 以数字的形式显示协议名称 -t 显示tcp -a 显示全部的进程 -u 显示 udp 示例：ss 查看socket连接状态，与netstat类似用法：ss [参数] 参数介绍： -l 列出所有打开的端口 -p 显示进程的名称和 pid -n 以数字的形式显示协议名称 -t 显示tcp -a 显示全部的进程 -u 显示 udp -m 查看内存情况 -s 显示socket摘要 示例：系统别名alias 查看系统指令别名alias 别名='实际命令名' 为某个命令起别名type -a 别名 查看指定别名对应的命令unalias 别名 取消某个别名用户相关logout 退出当前用户/etc/passwd 保存用户相关信息/etc/group 保存用户组相关信息/etc/shadow 保存用户密码信息用户用户UID 用户唯一ID，等同于身份证号GID 用户组唯一ID，等同于户口本号root用户UID root用户UID是0GID root用户GID是0普通用户UID 从1000开始，由超级管理员创建GID 从1000开始普通用户在被创建时，会在系统中创建一个同名的组（主属组）虚拟用户（系统用户）UID 1~999创建用户useradd 创建用户，默认从1000开始递增（或者从当前最大值开始递增）用法：useradd [参数] 用户名 - 新建用户的同时会自动构建一个属组（组名和用户名一样，也叫`主属组`） - 普通用户家目录位于`/home`目录下 参数介绍： -u UID 指定UID，不允许重复值 -s Shell 指定解释器版本 -G 组名或GID 指定副属组，副属组需已存在 -g 组名或GID 指定主属组，主属组需已存在 -c 添加用户描述信息 -d 指定用户登陆时的起始目录（家目录），如果把其他用户的家目录当成自己的，会导致其他用户命令提示符消失，且难以统一管理。 -e 指定账户的过期时间 -f 缓冲天数，密码过期后多少天关闭该账户 -m 自动建立用户的登录目录 -r 创建系统用户 -D 参数 修改配置文件`/etc/default/useradd`的默认值删除用户userdel 删除用户用法：userdel [参数] 用户名 参数介绍： -r 删除用户时同时删除家目录修改用户usermod 修改用户用法： usermod [参数] 用户名 - 如果只修改用户名，则UID、GID、所属组不变 参数介绍： -l 新用户名 将`旧用户名`修改成`新用户名` -g 新GID 将`旧GID`修改为`新GID`（更换主属组），新GID需已存在 -u 新UID 将`旧UID`修改为`新UID`，不能重复 -s shell解释器路径 修改用户的shell解释器版本 -d 路径 修改用户家目录查看用户信息id 查看用户ID信息[uid、uname、gid、副属组]whoami 查看当前用户w 展示当前已登陆的用户信息第一行显示的是系统时间,系统从启动到运行的时间,系统运行中的用户数量和平均负载 第二行信息 user 用户名 TTY 用户使用终端号 FROM 标识用户从哪来 [终端所在机器的 ip地址] LOGIN@ 登录系统的时间 IDLE 代表终端空闲时间 JCPU 该终端所有进行以及子进程使用系统的总时间 PCPU 活动进程使用系统的时间 WHAT 用户执行的进程名称who 等同于w的简化版lastlog 查看当前机器所有用户最近登录信息用户密码密码root用户可以给其他用户设置密码普通用户设置密码后才能登录root用户可以随意设置密码普通用户设置密码需遵守规则普通用户限制出错重试3次passwd 修改密码用法：passwd [参数] 用户名 参数介绍： -n 至少多少天不可修改密码 -x 最多多少天不可修改密码 -w 密码过期前多少天通知用户 -i 过期多久禁止用户登录 示例： 1. 设置user6的密码，7~60天内禁止修改密码，过期前三天提示，账户过期7天后禁止登录 passwd user6 -n 7 -x 60 -w 3 -i 7chpasswd 批量修改密码用法：chpasswd - 交互式窗口，修改格式 username:passwd - Ctrl^D 退出交互 - 需要root用户使用 示例： 1. 设置user0~user10的密码为11223344 chpasswd [回车] user0:11223344 user1:11223344 user2:11223344 此处省略一些内容 user10:11223344 [Ctrl^D]用户切换su 用户 只切换用户身份，不切换环境变量su - 用户 切换用户身份和环境变量用户提权sudo 临时获得root权限，可以执行一些普通用户没有权限执行的命令加入sudo用户组vi /etc/sudoers ，找到以下行：## The COMMANDS section may have other options added to it. ## ## Allow root to run any commands anywhere root ALL=(ALL) ALL参照格式，在root行后添加以下行 用户名 ALL=(ALL) ALL保存退出，重启系统生效。用户创建流程系统读取/etc/login.defs（用户定义文件）、/etc/default/useradd（用户默认配置文件），根据这两个文件定义的规则创建新用户向/etc/passwd和/etc/group文件添加用户信息，向/etc/shadow中添加用户密码，向/etc/gshadow中添加组密码根据/etc/default/useradd文件创建新用户家目录将/etc/skel中的所有文件复制到新用户的家目录/etc/login.defs参数介绍MAIL_DIR /var/spool/mail # 系统发送邮件的位置 PASS_MAX_DAYS 99999 # 密码最长使用天数 PASS_MIN_DAYS 0 # 密码最短更换时间 PASS_MIN_LEN 5 # 密码最短长度 PASS_WARN_AGE 7 # 密码失效前几天发出警告 UID_MIN 1000 # 新建普通用户最小UID UID_MAX 60000 # 新建普通用户最大UID SYS_UID_MIN 201 # 新建系统用户最小UID SYS_UID_MAX 999 # 新建系统用户最大UID GID_MIN 1000 # 新建普通用户组最小GID GID_MAX 60000 # 新建普通用户组最大GID # System accounts SYS_GID_MIN 201 # 新建系统用户组最小GID SYS_GID_MAX 999 # 新建系统用户组最大GID CREATE_HOME yes # 是否自动创建家目录 UMASK 077 默认权限掩码 # This enables userdel to remove user groups if no members exist. # USERGROUPS_ENAB yes # Use SHA512 to encrypt password. ENCRYPT_METHOD SHA512 # 密码加密算法/etc/default/useradd参数介绍# useradd defaults file GROUP=100 HOME=/home # 在 /home 目录下 创建用户的家目录 INACTIVE=-1 # 开启用户过期 EXPIRE= SHELL=/bin/bash # 新用户默认的解释器 SKEL=/etc/skel # 用户环境变量文件的存放目录 CREATE_MAIL_SPOOL=yes用户组用户组 方便管理同一组用户GID 组与组之间区分用户与组的关系一对一 一个用户存在一个组里，一个组里只有一个用户一对多 一个用户可以加入多个组多对一 多个用户可以加入一个组多对多 多个用户可以存在多个组中创建组groupadd 创建组，默认从1000开始递增（或者从当前最大值开始递增）用法：groupadd [参数] 组名 参数介绍： -g GID 指定GID，不允许重复值修改组groupmod 修改组信息用法：groupmod [参数] 组名 参数介绍： -g 新UID 修改GID，不允许重复值，不允许小于1000 -n 新组名 修改组名删除组groupdel 删除组，需要该组未充当用户的主属组才可以删除用法：groupdel 组名 - 用户的主属组不能删除[创建用户时，会自动分配主属组(主属组和用户名相同)] - 若组内存在用户，该组不可删除 示例： 1. 创建test组 groupadd test 2. 创建demo组并设置gid groupadd -g 1002 demo 3. 将test组的gid修改为1003 groupmod -g 1003 test 4. 将demo组的名字修改为DEMO groupmod -n DEMO demo 5. 删除DEMO组 groupdel DEMO 练习： 1. 新建用户组group01 groupadd group01 2. 新建用户组group02并指定gid为1111 groupadd group02 -g 1111 3. 将group01的组名修改为group11 groupmod -n group11 group01 4. 删除用户组group02 groupdel group02 5. 基于root用户新建文件/dir2/demo.txt练习vi编辑器指令 6. 新建用户并指定shell解释器版本为/sbin/nologin useradd user01 -s /sbin/nologin 7. 新建用户并指定主属组为user02副属组为 group11 useradd user03 -g user02 -G group11添加组成员gpasswd 管理组成员用法：gpasswd [参数] 组名 参数介绍： -a 用户 添加用户到组 -M 用户1,用户2,用户3 添加多个用户到组 -d 用户 从组中删除用户主机相关hostname 查看当前主机名hostnamectl set-hostname 新主机名 修改当前主机名，重启生效网络相关ip a 或 ip addr 查看主机IP地址wget 文件下载器- 默认将文件下载到当前目录下 参数介绍： -O 路径 将文件保存到指定路径curl 文件下载器参数介绍： -o 路径 将文件保存到指定路径远程登陆sshopenssh-server 提供服务 openssh-clients 客户端 sshd服务默认的端口号：22 安装1. 安装 yum install openssh-server # 安装ssh服务端 2. 查看sshd启动状态 systemctl status sshd # 查看sshd启动状态 3. 如果sshd未启动 systemctl start sshd # 启动sshd 4. 关闭防火墙 systemctl stop firewalld # 关闭防火墙使用用法：ssh [参数] 用户名@ip 参数介绍： -p 端口号 指定端口连接 示例： 1. 连接到服务器192.168.119.20，用户名是root ssh root@192.168.119.20证书与密钥ssh生成密钥对ssh-keygen [回车] Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): # 设置私钥保存位置 Enter passphrase (empty for no passphrase): # 输入密码，回车代表密码为空 Enter same passphrase again: # 再次输入密码 Your identification has been saved in /root/.ssh/id_rsa. # 私钥保存位置 Your public key has been saved in /root/.ssh/id_rsa.pub. # 公钥保存位置 The key fingerprint is: SHA256:a+zSpj2nrjz9XgdBUiNYbN46BKg0Id309MRuqc3o09U root@mkirin # 密钥指纹 The key's randomart image is: +---[RSA 2048]----+ | ...+...==.+ | | .+ oooo++ . | | . o .=.o. | | . * .. | | SB ... | | .o.= ..E | | ++. o. . | | .o+B o. . | | +B=Bo | +----[SHA256]-----+修改配置/etc/ssh/sshd_config sshd服务器配置文件端口号修改：编辑/etc/ssh/sshd_config vi /etc/ssh/sshd_config找到Port 22行，将该行前的#删除，修改22为指定的端口号 Port 2222保存文件重启系统硬件相关init 0 切换运行级别为0，此级别代表关机init 6 切换运行级别为6，此级别代表重启shutdown -r [参数] 重启shutdown -r 10 10分钟后重启shutdown -r 0 立即重启shutdown -r now 立即重启shutdown -h [参数] 关机shutdown -h 10 10分钟后关机shutdown -h 0 立即关机shutdown -h now 立即关机reboot 重启poweroff 关机，立即关闭系统并切断电源halt 关机，立即关闭系统，但需要手动切断电源 Init等级 0：停机或者关机（千万不能将initdefault设置为0） 1：单用户模式，只root用户进行维护 2：多用户模式，不能使用NFS(Net File System) 3：完全多用户模式（标准的运行级别） 4：安全模式 5：图形化（即图形界面） 6：重启（千万不要把initdefault设置为6）时间相关date 查看当前时间用法：date '+参数' 参数介绍： %F 只查看当前日期的年月日 %X 只显示当前时间的时分秒 %s 从1970年1月1日0时0分0秒到 现在 过了多少秒 %S 秒 %c 直接显示日期与时间（年月日 星期 时分秒） %x 直接显示日期（年月日） %T 显示时分秒 HH:mm:dd[24小时] %r 显示时分秒[12小时] %p 显示上午还是下午 %Z 显示时区 %w 一周中的第几天 %a 星期几(简写) %A 星期几 %b 月份(简写) %B 月份()全称 -s 时间 手动设置时间ntp 网络校时安装 yum install ntp使用 ntpdate 时间服务器网址中国时间服务器 cn.pool.ntp.org定时任务（计划任务）后台运行,到了预定的时间就会自动执行的任务。 前提是,事先手动将计划任务设定好例如： 1. 周期性的任务执行 2. 清空 /tmp 目录下的内容 3. mysql数据库的备份 4. redis数据备份一次调度执行at 定时任务工具,依赖于atd 服务 适用于执行一次就结束的调度任务。安装：yum install at systemctl status atd # 查看 atd 计划任务的开启状态 systemctl start atd # 若服务未开启则手动开启用法： #方式一 语法格式： 1. at 时间 #回车 2. 输入你的计划任务指令 3. ctrl + D # 任务写完了 # 方式二 at 时间 < 文件 参数介绍： -l 查看计划 -d 删除计划 时间细节： now+1min # 一分钟以后 now+10min # 十分钟以后 HH:MM # 小时:分钟 10:30 YYYY-mm-dd # 年月日 2030-10-10 noon # 刚好中午12点 midnight # 刚好午夜12点 teatime # 下午茶时间 下午 4点 tomorrow # 明天 now+1hours # 一小时以后 now+1minutes # 1分钟以后 now+1days # 一天以后 now+1weeks # 一周以后 示例： 1. 新建文件,存储任务 vim at.jobs 填充内容：touch /test4/dir1/a.txt # 将任务设定时间指定 at 10:30 < at.jobs 2. 查看一次性任务 atq 或者 at -l 3. 取消计划任务 atrm 序号 或者 at -d 序号 4. 取消7号定时任务 atrm 7 # 取消指定的计划任务循环调度执行Cron是Linux系统中以后台进程模式周期性的执行命令， 或者指定程序任务的服务软件名 Linux系统启动以后,cron软件就会开机自启。 默认是定期(每分钟检查一次)检查系统中是否有需要执行的任务计划。 如果有，则按照计划进行。类似于我们生活中定的闹铃 cron 定时任务工具# 安装 cronie 软件 yum -y install cronie # 查看服务状态，确保服务开启 systemctl status crond.service # 存储位置 /var/spool/cron # 查看系统的循环调度任务 `ll /etc | grep 'cron*'` cron.d # 系统定时任务 cron.daily # 每天的任务 cron.hourly # 每小时的任务 cron.monthly # 每月的任务 cron.weekly # 每周的定时任务 # 使用者权限文件 /etc/cron.deny # 该文件中所列出的用户不允许使用 crontab命令 /etc/cron.allow # 该文件中所列用户允许使用crontab命令,默认不存在,需要手动创建,可以忽略 /etc/crontab # 系统计划任务 用法： 方式一： crontab -e 50 21 * * * touch a.txt # 在crontab的编辑器中编写任务指令 方式二： # 1. 准备已经写好了指令的脚本文件(后缀是 .sh) vim /root/cronDemo.sh 文件内容 #!/bin/bash mkdir -p /test4/fileDemo touch /test4/fileDemo/a.txt # 2. 编辑周期计划任务 crontab -e * * * * * bash /root/cronDemo.sh # 直接执行任务脚本 参数介绍： -l # 列出当前用户的计划任务 -r # 删除当前用户的所有计划任务 -e # 编辑当前用户的计划任务 -u # 管理其他用户的计划任务,仅限root管理员 示例： 使用其他用户创建周期计划任务 1. 代替某个用户执行周期性计划任务 crontab -u 用户名 -e # 基于root用户 2. 查看某个用户的计划任务 crontab -u 用户名 -l 3. 删除指定用户的周期性计划任务 crontab -u 用户名 -rcron时间参数介绍（从左向右）：* * * * * bash /root/cronDemo.sh分钟小时日月周指令0-590-231-311-120-7，其中0和7都代表星期天cmd*****bash /root/cronDemo.sh支持的符号描述备注*代表任何可能的值 -定义一个范围 ,分隔数值列表 /指定数值的增量 L表示月份的最后一天或星期几的最后一个 W表示最接近指定日期的工作日 #用于指定月份中的第几个星期几当前cron不一定支持cron演示分钟小时日月周指令描述0002***指令1每天 凌晨2点整 执行指令100021**指令2每个月的 1号 凌晨2点整 执行指令20002142*指令3每年的 2月 14号 凌晨2点整 执行指令30002**7指令4每周日 凌晨2点整 执行指令40002*65指令5每年 6月的 周五 凌晨2点整 执行指令500021,5,8**指令6每个月的 1号,5号,8号 凌晨2点整 执行指令600021-8**指令7每个月的 1号到8号 凌晨2点整 执行指令7008-14*3指令8每个月 第二个 星期三 执行指令8日志Linux系统日志对于程序员来说,是了解系统运行的主要途径,因此需要对Linux日志系统有一个详细的了解。 Linux系统内核和许多程序在工作中都会产生各种错误信息、警告信息、其他的一些提示信息， 这些信息都记录在各自的日志文件中, 完成日志记录的过程需要使用的程序rsyslog rsyslog可以根据日志的类别和优先级将日志保存到不同的文件中 常见的日志文件(系统,进程,应用程序)系统主日志 /var/log/messages认证与安全日志 /var/log/secure邮件日志 /var/log/maillogcron日志 /var/log/cron系统启动日志 /var/log/dmesgyum日志 /var/log/yum.log# 动态查看系统主日志文件的尾部 tail -f /var/log/messages # 记录认证,安全的日志 tail -f /var/log/secure # 跟邮件相关 postfix tail -f /var/log/maillog # crond at进程产生的日志 tail -f /var/log/cron # 系统启动相关 tail -f /var/log/dmesg # yum相关的日志 tail -f /var/log/yum.log日志优先级日志级别分为： 9种 日志级别代号 0 ~ 7 0 debug # 记录调试信息 日志信息最多 1 info # 一般信息的日志 最常用 2 notice # 最具有重要性的信息 3 warning # 警告信息 4 error # 错误级别 阻止某个功能或者软件 正常工作的信息 5 crit # 严重错误级别 阻止整个系统或者整个软件正常工作的信息 6 alert # 需要立刻修改的信息 7 emerg # 内核崩溃等严重信息 none # 什么都不记录日志轮转与切割1. 如果没有日志轮转,日志文件会越来越大 2. 可以丢掉系统中旧文件,节省空间 3. 可以针对日志文件进行分割，如：按照大小分割：10MB/个 按照时间轮转：1天/次，1周/次 logrotate配置文件位置：/etc/logrotate.conf具体信息参考上图，代码参考以下内容 weekly # 轮转周期 rotate 4 # 保留4份 create #轮转后创建新文件 dateext # 使用日期作为新文件后缀 include /etc/logrotate.d # 包含该目录下的配置文件 /var/log/wtmp { # 对指定日志文件设置轮转方法 monthly # 一月一次 create 0664 root utmp # 轮转后创建新文件并且设置权限 minsize 1M # 最小大小1M才轮转，否则即使到时间也不轮转 rotate 1 # 保留一份 } /var/log/btmp { missingok # 允许丢失，丢失不提示 monthly create 0600 root utmp rotate 1 } 用法： 参数介绍： -d, --debug ：debug 模式，测试配置文件是否有错误。 -f, --force ：强制转储文件。 -m, --mail=command ：压缩日志后，发送日志到指定邮箱。 -s, --state=statefile ：使用指定的状态文件。 -v, --verbose ：显示转储过程。 示例： 1. 轮转日志/var/log/yum.log cat /etc/logrotate.d/yum 文件内容： /var/log/yum.log { missingok # 丢失不提示 notifempty # 空文件不轮转 maxsize 30k # 到达30K就轮转，无论是否到时间 yearly # 每年一次 create 0600 root root # #轮转后创建新文件且设置权限 } 2. 手动轮转 logrotate -f 轮转配置文件 案例：配置 nginx的日志轮转 access.log error.log #1. 在 /etc/logrotate.d/ 创建一个文件 nginx #2. 文件内容 /usr/local/nginx/logs/*.log{ missingok notifempty daily size 100k create 0600 root root }文件存储磁盘分区方式注意： 从MBR分区转到GPT分区(或者反过来)是可以的，但是数据会全部丢失MBRMBR （MSDOS根据分区表来指定分区规则，叫做主引导记录）大小：<2TB分区工具：fdisk分区限制：一共可以划分14个分区(主分区、扩展分区、逻辑分区)，例如 3主 + 1扩展 + 逻辑分区一块硬盘最多4个主分区一块硬盘最多1个拓展分区GPTGPT（GUID分区表）大小：>2TB分区工具：gdisk分区限制：一共可以划分128个主分区分区工具fdisk MBR分区工具安装：yum install util-linux用法：fdisk [参数] 路径 参数介绍： -l 列出分区表 内置命令： m 帮助 n 创建新分区 d 删除分区 w 将更改写入磁盘并退出 q 退出不保存 a 活动分区标记/引导分区 l 显示分区类型 p 显示分区信息 t 设置分区号 v 进行分区检查 示例： 1. 列出分区表 fdisk -l 2. 创建分区 fdisk /dev/nvme0n2 欢迎使用 fdisk (util-linux 2.23.2)。 更改将停留在内存中，直到您决定将更改写入磁盘。 使用写入命令前请三思。 Device does not contain a recognized partition table 使用磁盘标识符 0xaf3e45ca 创建新的 DOS 磁盘标签。 命令(输入 m 获取帮助)：n Partition type: p primary (0 primary, 0 extended, 4 free) # 主分区 e extended # 拓展分区 Select (default p): p # 选择分区类型 分区号 (1-4，默认 1)：1 # 选择分区号 起始 扇区 (2048-41943039，默认为 2048)：2048 # 选择起始扇区，回车表示默认 Last 扇区, +扇区 or +size{K,M,G} (2048-41943039，默认为 41943039)：+1G # 选择结束扇区 分区 1 已设置为 Linux 类型，大小设为 1 GiBgdisk GPT分区工具，与fdisk使用方式基本相同安装：yum install gdisk用法：gdisk [参数] 路径 参数介绍： 内置命令： ?/help 帮助 n 创建新分区 d 删除分区 w 将更改写入磁盘并退出 q 退出不保存 l 显示分区类型 p 显示分区信息 t 设置分区号 v 进行分区检查 示例： 1. 创建分区 gdisk /dev/nvme0n2 GPT fdisk (gdisk) version 0.8.10 Partition table scan: MBR: protective BSD: not present APM: not present GPT: present Found valid GPT with protective MBR; using GPT. Command (? for help): n Partition number (1-128, default 1): 1 # 选择分区号 First sector (34-41943006, default = 2048) or {+-}size{KMGTP}: 34 # 起始扇区 Information: Moved requested sector from 34 to 2048 in order to align on 2048-sector boundaries. Use 'l' on the experts' menu to adjust alignment Last sector (2048-41943006, default = 41943006) or {+-}size{KMGTP}: +1G # 结束扇区 Current type is 'Linux filesystem' Hex code or GUID (L to show codes, Enter = 8300): # 设置分区类型，回车表示默认 Changed type of partition to 'Linux filesystem'分区格式化mkfs 用法：mkfs [参数] 路径 参数介绍： -t 格式 指定内容格式，默认为`ext2` 示例： 1. 将 /dev/sdc1 格式化为 ext4 格式的 文件系统 mkfs -t ext4 /dev/sdc1 2. 将 /dev/sdc2 格式化为 xfs 格式的文件系统 mkfs -t xfs /dev/sdcmkfs.[格式] 用法：mkfs.[格式] [参数] 路径 格式介绍： ext4 使用ext4格式 xfs 使用xfs格式 fat 使用fat格式 参数介绍： -c 格式化前检查分区是否有坏块 示例： 1. 将 /dev/sdc1 格式化为 ext4 格式的 文件系统 mkfs.ext4 /dev/sdc1 2. 将 /dev/sdc2 格式化为 xfs 格式的文件系统 mkfs.xfs /dev/sdc分区挂载mount 临时挂载，断电失效用法：mount [参数] 源路径 目标路径 参数介绍： 示例 1. 挂载/dev/sda到/mnt目录 mount /dev/sda /mntfstab 分区表配置，开机自动挂载/etc/fstab 配置文件位置fstab参数介绍： <设备> <挂载点> <文件系统类型> <挂载选项> <dump 备份> <fsck 启动检查>示例：设备挂载点文件系统类型挂载选项dump 备份fsck 启动检查/dev/mapper/centos-root/xfsdefaults00UUID=a50ffbf4-0817-4619-b993-9826ea53643a/bootxfsdefaults00/dev/mapper/centos-swapswapswapdefaults00开机自启动脚本挂载/etc/rc.d/rc.local 开机自启动脚本，注意需要有执行权限编写mount挂载命令放入其中，即可实现开机挂载#!/bin/bash # THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES # # It is highly advisable to create own systemd services or udev rules # to run scripts during boot instead of using this file. # # In contrast to previous versions due to parallel execution during boot # this script will NOT be run after all other services. # # Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure # that this script will be executed during boot. touch /var/lock/subsys/local mount /dev/sda /mnt # 挂载/dev/sda到/mnt目录磁盘查看lsblK 查看磁盘分区blkid 查看磁盘UUID用法：blkid [参数] 路径 参数介绍： 示例： 1. 查看分区/dev/sdc1的UUID blkid /dev/sdc1文件与目录Linux文件目录组成/ ├── boot 存放系统内核与启动文件 ├── dev 存放硬件设备相关信息 ├── etc 存放系统配置文件 │ ├── resolv.conf 设置域名解析 │ ├── hostname 设置主机名 │ ├── motd 设置开机提示语 │ ├── os-release 查看发行版和版本号 │ └── sysconfig │ └── network-scripts │ └── ifconfig-xxx 设置网络环境，如动态IP等 ├── home 普通用户的主目录 ├── media 可卸载的存储介质挂载点 ├── mnt mount文件的临时挂载点 ├── opt 应用程序包的安装目录 ├── proc 系统内存的映射目录，提供内核与进程信息 ├── root 特权用户目录 ├── run 存放组件运行时所需文件[文件夹] ├── srv 存放组件运行时所需文件 ├── temp 存放临时文件 ├── usr 存放用户程序 └── var 存放运行时内容会改变的文件，如日志等特殊文件/dev/null 黑洞文件，只进不出。/dev/zero 提供无限空字符(0x00)文件分类 -：普通文件 d：目录文件 l：链接文件 b：块设备文件 c：字符设备文件 p：管道文件 s：socket套接字文件文件路径绝对路径 /文件 /文件夹/文件 /mysql.rpm # 根目录下的mysql.rpm /root/mysql.rpm # root目录下的mysql.rpm相对路径 ./ 当前目录 ../ 上级目录 ./mysql.rpm # 当前目录下的mysql.rpm ../mysql.rpm # 上级目录下的mysql.rpm创建目录mkdir 创建文件夹mkdir /path/{a,b,c} 一次创建指定数量个文件夹mkdir /path/{1..n} 一次创建n个文件夹用法：mkdir [参数] 文件夹（包含路径） 参数介绍： -p 递归创建文件夹 -v 显示详细创建信息创建文件touch 创建普通文件；修改文件时间touch /path/{file1,file2,file3} 一次创建指定数量个文件touch /path/file{1..n} 一次创建n个文件用法：touch [参数] 文件（包含路径） 参数介绍： -t [年月日时分] 修改创建时间为指定的年月日时分 -r [file1] 将目标文件的创建时间修改为file1相同 -v 显示详细创建信息 案例： 1. 修改filez.png时间为当前系统年份的7月6号16时30分 touch -t 07061630 filez.png # 年份为空，自动调用系统当前年份 2. 修改filez.png时间为2025年7月6号16时30分 touch -t 202507061630 filez.png删除文件或文件夹rm 删除文件或文件夹用法：rm [参数] 文件或目录 参数介绍： -i 删除时询问 -r 删除目录，不加该参数只能删除文件 -f 强制执行，不显示提示信息 -v 显示详细删除信息复制文件或目录cp 复制文件或文件夹用法：cp [参数] 源文件 目标文件 参数介绍： -i 覆盖前询问 -r 递归复制目录和子文件 -f 强制执行，不显示提示信息 -v 显示详细复制信息 -d 复制的时候保持软链接 -p 完全复制，包括权限时间戳等与原文件相同 -a 等价于使用-pdr移动文件或目录mv 移动文件或目录；重命名文件或目录用法：mv [参数] 源路径 目标路径 参数介绍： -i 覆盖前询问 -f 强制执行，不显示提示信息查看文件或目录pwd 查看当前工作目录ls 列出文件夹下内容，隐藏文件默认不展示。用法：ls [参数] 路径 参数介绍： -a 列出指定路径下所有内容，包括隐藏文件 -l 列出指定路径下文件的详细信息 -h 配合-l使用，查看文件详细大小 --full-time 查看详细时间 -t 按照最后一次修改时间降序排序。 -F 在不同文件结尾输出不同符号，如： 文件夹后是 / 可执行文件后是 * 软链接后是 @ . 开头的是隐藏文件 普通文件无后缀 -d 只列出指定文件夹信息 -r 逆转排序 -S 从大到小排序 -i 显示文件inode编号stat 查看文件详细信息（访问和修改时间、属性改变时间）file 查看文件类型文件内容查看cat 查看文件内容用法：cat [参数] 文件 参数介绍： -n 显示行号 -A 显示标记符号（制表符、换行符等）head 查看文件头部内容，默认是10行用法：head [参数] 文件 参数介绍： -数字 查看文件头部指定数量行的内容tail 查看文件尾部内容，默认是10行用法：tail [参数] 文件 参数介绍： -数字 查看文件尾部指定数量行的内容 -f 用于动态变化的文件，Ctrl^C退出监测grep 查找、过滤文件内容关键字用法：grep '参数' 文件 参数介绍： ^字符串 以字符串开头的行 字符串$ 以字符串结尾的行 -n 查看行号 -i 不区分关键字大小写 -E 开启ERE正则表达式拓展 -v 反向查找，只打印不匹配的行 -w 只显示全字符合的列 用例： 1. 过滤带有root的行 grep 'root' /etc/passwd 2. 过滤以root开头的行 grep '^root' /etc/passwd 3. 过滤以nologin结尾的行 grep 'nologin$' /etc/passwdless 分页查看内容比较大的文件，按q退出用法：less 文件 功能说明： 空格 翻页 回车键 下一行 方向键↑↓ 上下滚动 /关键字 在文件中查找关键字并高亮显示 n 搜索时上翻 N 搜索时下翻more 分页查看文件，看完自动退出，窗口底部展示百分比用法：more 文件 功能说明： 空格 翻页 回车键 下一行echo 字符串 输出指定字符串，默认输出到当前控制台文件内容切割cut 提取文件片段用法：cut [参数] 文件 参数介绍： -c 提取指定位置的字符 -d 符号 指定分隔符符号，默认分隔符是空格 -f 与-d连用，置顶显示区域，与-c作用类似 示例： 1. 提取每行第四个字符 cut -c 4 /etc/passwd 2. 提取每行第4~8个字符 cut -c 4-8 /etc/passwd 3. 提取每行前8个字符 cut -c -8 /etc/passwd cut -c 1-8 /etc/passwd 4. 提取每行第8个到末尾的字符 cut -c 8- /etc/passwd 5. 提取每行第4、6个字符 cut -c 4,6 /etc/passwd 6. 提取每行第1-3、6-8个字符 cut -c 1-3,6-8 /etc/passwd 7. 以':'为分隔符切割，保留第1段 cut -d : -f 1 /etc/passwd 8. 以':'为分隔符切割，保留第1~3段 cut -d : -f 1-3 /etc/passwd文件排序与去重sort 按照制定规则对文件进行排序用法：sort [参数] 文件 参数介绍： -b 忽略前导的空白区域 -n 根据字符串数值比较，默认升序 -r 反转排序 -u 去重排序，与-c连用 -t 分隔符 指定分隔符，默认是空格 -k [位置1，位置2] 指定某个排序规则的作用域：位置1~位置2 示例： 1. 对IP第4段（主机号）进行排序 sort -n -t '.' -k 4 ./ip.txt 2. 对1.txt进行升序去重排序 sort -n -u ./1.txt 1.txt 内容： 0 a 1 c 2 s 3 a 4 f 5 e 6 g 0 a 7 b 8 h 9 y 0 u 9 j 7 k 0 a 5 i 4 o 2 l 9 y 1 p ip.txt 内容 192.168.10.1 192.168.10.20 192.168.10.15 192.168.10.2 192.168.10.3 192.168.10.5 192.168.10.2 192.168.10.3 192.168.10.7 202.184.250.20 138.4.52.61uniq 输出或忽略文件中的重复行，只能去除连续的相邻行。一般与sort连用用法：uniq [参数] 文件 1.排序排序命令进行排序 2.使用uniq命令去重或统计 参数介绍： -c 统计每一行的重复次数（连续相邻行） -d 统计出现两次及以上的行 -u 统计只出现一次的行 示例： 1. 对sort排序后的输出进行去重 sort -n ./1.txt | uniq 2. 对sort排序后的输出进行重复次数统计，统计每一行 sort -n ./1.txt | uniq -c 3. 对sort排序后的输出进行统计，只统计重复行 sort -n ./1.txt | uniq -c -d 4. 对sort排序后的输出进行统计，只统计重复一次的行 sort -n ./1.txt | uniq -c -u 5.查看哪些IP被占用 sort -n -t '.' -k 4 ./ip.txt | uniq -c -d 6.查看哪些IP处于空闲状态 sort -n -t '.' -k 4 ./ip.txt | uniq -c -u文件编辑 vi的文本模式 工作模式命令模式 [ESC]无法编辑只能查看编辑模式 [i,a,A,o,O]可以编辑可以查看尾行模式 [:]保存文件退出编辑器可视模式 [ESC,Shift^v,Ctrl^v]可视块可视行vi 系统默认的文本文件编辑器vim 高级文本编辑器，编辑器之神用法：vi 文件 功能说明： 1. 进入编辑模式 i 在光标处进入编辑模式 a 在当前光标后面进入编辑模式 A 在光标所在行的行尾进入编辑模式 o 在光标下一行进入编辑模式 O 在光标上一行进入编辑模式 2. 命令模式 光标定位： 方向键 ↑ ↓ ← → 按键 h(←) j(↓) k(↑) l(→) 0 回到行首（等同于HOME按键） $ 回到行尾（等同于END按键） gg 回到页面左上角（文本顶部） G 回到页面右下角（文本底部） 3G 进入第3行 4G（进入第四行） /关键字 查找关键字 n 跳转到下一个搜索结果 N 跳转到上一个搜索结果 复制： yy 复制当前行 3yy 从光标处复制3行 5yy（从光标处复制5行） ygg 从当前光标复制到页首（区域复制） yG 从当前光标复制到页尾（区域复制） 粘贴： p 粘贴剪贴板到本行下方 P 粘贴剪贴板到本行上方 删除 dd 删除光标所在行（向下删除） 3dd 从光标处向下删除3行 5dd（从光标处向下删除5行） dgg 从当前光标删除到页首（区域删除） dG 从当前光标删除到页尾（区域删除） d^ 删除光标所在位置到行首之间的内容（光标到行首） x 删除光标处的内容 D 删除光标所在位置到行尾之间的内容（光标到行尾） u 撤销 替换： r 替换修改光标处的字符 3. 尾行模式 : 进入尾行模式 :3 进入第三行 :w 保存 :q 退出 :q! 强制退出不保存 :wq 保存并退出 :wq! 强制保存退出 4. 可视化模式 Ctrl^v 可视块模式 Shift^v 可视行模式 5. 查找替换 :s/原内容/新内容/ 替换光标所在行的原内容为新内容，只匹配替换一次 :3 s/原内容/新内容/ 替换第3行的原内容为新内容，只匹配替换一次 :1,3 s/原内容/新内容/ 替换第1~3行的原内容为新内容，只匹配替换一次 :% s/原内容/新内容/ 替换所有行的原内容为新内容，只匹配替换一次 :% s/原内容/新内容/g 替换所有行的原内容为新内容，全部匹配替换 6. 设置环境 :set nu 设置行号 :set nonu 取消设置行号 :set list 显示控制字符，可以查看筛选带行尾空格的行emacs 高级文本编辑器，神的编辑器文件权限 权限分类 权限分配所有者所属组其他用户权限项读写执行读写执行读写执行字符表示rwxrwxrwx数字表示421421421chmod 设置文件权限对软链接的修改只影响软链接自身，与原文件无关用法：chmod [参数] 文件或目录 参数介绍： u 所有者 g 所属组 o 其他人 a 所有人 + 添加权限 - 撤销权限 = 只留下某个权限，其他权限撤销 r 读权限 w 写权限 x 执行权限 数字 三位数字，如777、755等代表权限的数字 -R 递归设置权限chown 设置所属用户/组用法：chown [参数] 路径 - chown 用户 文件 修改所有者 - chown :组 文件 修改属组 - chown 用户:组 文件 修改所有者和所属组 参数介绍： -R 递归设置权限 -v 显示详细信息chgrp 修改属组用法：chgrp [参数] 文件或文件夹 -c 只输出改变的部分的详细信息 -v 输出全部详细信息 -h 只对符号链接的文件进行修改 -R 递归设置权限 -f 不显示错误信息umask 权限掩码，用于限制新文件权限新文件被创建时，最初的权限由umask决定用户每次进入系统时，umask命令都会被执行并自动设置掩码，改变新建文件初始的权限umask只对当前终端有效，如需永久保存，请写入脚本计算方法： 777 - mask掩码值 = 新文件权限 用法：umask [参数] 权限掩码 只输入umask，会展示当前掩码值 参数介绍： -S 以字母形式显示权限掩码 -p 以数字形式展示 umaskchattr 更改文件的扩展属性，比chmod更改权限更底层用法：chmod [参数] 文件 参数介绍： -R 递归设置权限 -v 显示详细信息 + 添加模式 - 移除模式 = 指定模式 a 只能向文件中添加数据,不得删除 A 不让系统修改文件最后访问时间 i 文件不能被删除,改名,修改内容 示例： 1. 给 d.txt 增加 i 模式 chattr +i d.txt rm -f d.txt # 删除失败 2. 查看 d.txt 的模式 lsattr d.txt -------i------ d.txt 3. 取消 i 模式 chattr -i d.txt 4. 查看 d.txt 的模式 lsattr d.txt ------------- d.txt 5. 演示 a 模式：只能向文件中增加内容 不得更改 chattr +a a.txt echo "测试数据" > a.txt # 覆盖源数据 -bash: a.txt: 不允许的操作 echo "测试数据" >> a.txt # 可以追加数据lsattr 用于查看文件的第二扩展属性(看底层模式)，与chattr结合使用用法：lsattr [参数] 路径 参数介绍： -R 递归列出目录以及子目录下的 chattr设置的模式 该参数默认存在 -V 显示程序版本 -v 显示文件版本 -a 列出目录中的所有文件 包括隐藏文件的属性 -d 只列出当前目录的模式 不展示子目录的模式文件查找参考章节：文件分类find用法： find 路径 [参数] 参数介绍： -P 路径 要查找的路径，可省略 -maxdepth 深度 查找是搜索的最大深度 -mindepth 深度 查找是搜索的最小深度 -atime 时间 按照文件访问时间查找 -n n天内访问过 n 正好n天访问过 +7 超过n天前访问过 -ctime 时间 按照文件的改变状态查找 -mtime 时间 按照文件修改时间查找 -name 名字 按照文件名查找 -group 按照文件的所属组查找 -perm 按照文件的权限查找 -size 大小[后缀] 按照文件按大小查找 b 位 c 字节 w 字[2字节] k KB M 兆 G 千兆 -type 类型 查找指定类型文件,参考文件分类章节 b 块设备 d 目录 c 字符设备 p 管道文件 l 符号链接 f 普通文件 s socket文件 -user 按照文件所有者进行查找 -path 路径 配合-prune 排除指定目录 -prune 使find不在指定目录中查找 -delete 删除找出的文件 -exec 命令 {} \; 对匹配的文件执行相应的shell命令，在执行后续shell命令时不提示 -ok 命令 {} \; 同上，在执行后续shell命令时会提示 -print 将匹配的结果标准输出 ! 取反 -a 取交集，与`&&`类似 -o 取并集，与`或`类似 示例： 1. 排除指定目录/dev find / -path '/dev' -prune -o -name 'nvme*' -print 2. 排除多个目录/dev /sys /usr 写法： \( -path -o -path \) find / \( -path '/dev' -o -path '/sys' -o -path '/usr' \) -prune -o -name 'nvme*' -print 3. 查找指定文件并查看权限属性 -exec find /root -type f -name 'mysql.rpm' -exec ls -al {} \; 4. 带提示的查看权限属性操作 -ok find /root -type f -name 'mysql.rpm' -ok ls -al {} \;文件计数wc 统计文件行数、单词数、字节数用法：wc [参数] 文件 参数介绍： -c 打印字节数 -m 打印字符数 -l 打印行数 -L 打印最长行的长度 -w 打印单词数 常用命令： 1. 统计在线用户数 who | wc -l文件链接关联：查看文件或目录软链接指向元数据（inode），如果元数据被删除，则软链接将无法打开硬链接指向文件的实际存储位置，即使元数据被删除，也不影响硬链接的正常使用ln 创建链接不加参数默认创建的是硬链接用法：ln [参数] 源路径 目标路径 参数介绍： -s 创建软链接输入输出0 标准输入(键盘)1 标准正确输出2 标准错误输出3~n 进程在执行过程中打开的其他文件& 混合，表示正确和错误混合输出管道与重定向管道| 链接两条命令，将命令1的输出传递给命令2的输入用法：cmd1 | cmd2xargs 通常与管道配合使用用法： 参数介绍： -d 分隔符 指定分隔符 -i 用`{}`代表查找出的文件 -I str 用字符串代表查找出的文件 -n 限制单个命令行的参数个数 示例： 1. 查找mysql.rpm并移动到/opt目录 - find /root -type f -name 'mysql.rpm' | xargs -i mv {} /opt/ - find /root -type f -name 'mysql.rpm' | xargs -I str mv str /opt/tr 从标准输入替换、删除、缩减字符，输出到标准输出，关联：文件排序与去重用法：tr [参数] 内容 参数介绍： -d 删除所有限定字符 -s 去除连续重复限定字符rev 反转输出的字符串顺序，与管道搭配使用示例： echo '123' | rev 输出：321history 查看终端执行命令的历史记录重定向输入重定向< 重定向文件内容到输入<<EOF 重定向<<EOF 和EOF之间的内容到输入示例： 1. 重定向输入 cat < redirect.txt ** 2. 通过重定向输入创建文件 ** cat > redirect.txt <<EOF hello world EOF # 调用键盘输入，输入EOF结束输入 2. 重定向错误输出 ls 2> redirect.txt 3. 重定向混合输出 ls 2&1> redirect.txt ls &> redirect.txt 4. 正确输出和错误输出分开存放 ls 1> reok.txt 2> reerr.txt 5. 只保留正确输出，错误输出丢弃 ls 1> reok.txt 2> /dev/null输出重定向> 覆盖文件内容>> 追加内容到文件尾示例： 1. 重定向输出（默认只重定向正确输出） ls > redirect.txt 2. 重定向正确输出 ls 1> redirect.txt 3. 重定向错误输出 ls 2> redirect.txt 4. 重定向混合输出 ls 2&1> redirect.txt ls &> redirect.txt 5. 正确输出和错误输出分开存放 ls 1> reok.txt 2> reerr.txt 6. 只保留正确输出，错误输出丢弃 ls 1> reok.txt 2> /dev/null文件打包tar用法：tar [参数] 路径 参数介绍： -c 打包文件 -x 解压文件 -z 使用压缩指令gzip，与-c或-x连用 -j 使用压缩指令bzip2 -v 显示详细信息 -f 指定目标文件路径 -A 把一个tar文件追加到另一个tar文件中 -C 解压缩到指定目录 -t 列出压缩包中的文件 -d 记录文件差异 -B 设置区块大小 -r 追加文件至归档结尾 -u 仅追加比归档文件中已有文件更新的文件 -l 文件系统边界设置 -k 解压时保留已有文件，不覆盖。 -m 保留文件不被覆盖 -w 确认压缩文件的正确性 -p 保留原来的文件权限与属性 --exclude 文件 排除指定的文件，其他文件解压缩 --remove-files 删除原始文件 示例： 1. 打包/tmp路径 tar -cvf tmp.tar /tmp 2. 解压tmp.tar文件 tar -xvf tmp.tar -C /gzip 打包/解包.gz文件用法：gzip [参数] 路径 参数介绍： -l 列出gz文件的文件信息zip 打包.zip文件默认未安装，需要手动安装用法：zip [参数] 目标文件 路径 参数介绍：unzip 解压.zip文件包默认未安装，需要手动安装用法：unzip [参数] 路径 参数介绍：rar 打包.rar文件默认未安装，需要手动安装用法：rar [参数] 路径 参数介绍：unrar 解包.rar文件默认未安装，需要手动安装用法：rar [参数] 路径 参数介绍：通配符与正则表达式通配符符号描述*匹配任意数量的任意字符?匹配任意一个字符^测试匹配测试开头的字符测试$匹配测试结尾的字符{1..100}1 2 3 .. 100 从1遍历到100{1..99..2}1 3 5 7 7 9 ..99 从1遍历到99，间隔为2{1,2}1 2 输出1和2[abcd]匹配abcd任意一个字符[1-9]匹配1-9任意一个字符[a-zA-Z]匹配a-zA-Z任意一个字符[[:upper:]]匹配所有大写字符[[:lower:]]匹配所有小写字符[[:alpha:]]匹配所有字母，包括中文[[:digit:]]匹配所有数字[[:alnum:]]匹配所有数字和字符[[:space:]]匹配所有空白[^1-9]表示取反，^和!相似示例 1. 查找根目录下，最大文件深度是3，所有以l开头，以小写字母结尾，中间任意出现一个字符的文件 find / maxdepth 3 -name 'l?[[:lower:]]' | rev | cut -d '/' -f 1 | rev 2. 获取/tmp目录下以任意一位数字开头，且以非数字结尾的文件 find /tmp -name '[[:digit:]]*[[:alpha:]]' | rev | cut -d '/' -f 1 | rev find /tmp -name '[[:digit:]]*[^[:digit:]]' | rev | cut -d '/' -f 1 | rev 3. 获取根目录下以非字母开头,后面跟着一个字母以及其他任意长度字符的文件 find / -name '[[:digit:]][[:alpha:]]*' | rev | cut -d '/' -f 1 | rev 4. 获取/tmp目录下所有以非字母开头的.txt文件,复制到/abc文件夹下 find /tmp -name '[[:digit:]]*.txt' | xargs -i cp {} /abc 5. 获取 /tmp 目录下所有的 .txt 结尾的文件 且 以 1 或者2 开头 find /tmp -name '[1,2]*.txt' 6. 引号' 强引用，所见即所得，单引号中的内容会原样输出，指令失效，转义字符失效" 弱引用，能够识别各种特殊的符号：变量 转义字符 解析结果示例： echo "$(date +%F)" 输出：2025-07-15 echo '$(date +%F)' 输出：$(date +%F)其他特殊符号; 分号，命令分隔符或是结束符，代表一条命令的结束| 管道符,传递指令的执行结果到另一个指令，关联：管道与重定向# 代表文件中的注释内容；root账户身份提示符$ $变量表示取出变量中保存的值；普通用户的身份提示符{} 生成序列；引用变量作为变量与普通字符的分隔逻辑符号&& 与符号，只有前一条命令执行成功，下一条命令才能执行|| 或符号，如果前一条命令执行完，下一条命令就不执行! 非符号在bash中取反 [!abcd]vim 编辑中表达强制的含义 wq! q!找出最近执行的指令例如： !! 再次执行上一次的指令 ! ls 列出最近一次 以 ls 开头的指令 并执行 ! cd 列出最近一次 以 cd 开头的指令 并执行正则表达式BRE 基本正则表达式[basic regular expression]BRE对应的元字符 ^ $ . [] *符号描述^用于模式匹配最左侧（开头）的行，如^gsc代表匹配以gsc开头的行$用于模式匹配最右侧（结尾）的行，如gsc$代表匹配以gsc结尾的行^$表示空行.匹配任意一个且只有一个字符，不能匹配空行\转义字符*匹配符号前一个字符连续出现0次或多次，如a*代表匹配0个或多个a.*组合符 匹配所有内容[包含空行]^.*组合符 匹配任意多个字符开头.*$组合符 匹配任意多个字符结尾的内容[abc]匹配[]集合内的任意一个字符 a b c 或者 [a-c][^abc]匹配除了a b c之外的任意字符，^表示对[abc]取反ERE 拓展正则表达式[extended regluar expression]ERE在BRE基础上增加了 () {} ? + |符号描述+匹配一个字符1次或多次，如a+代表匹配一个或多个a[ab]匹配[]中的字符1次或多次 例如[ab]+代表匹配ab一次或多次?匹配前一个字符1次或0次，如a?代表匹配1次或0次a|表示或者，同时过滤多个字符串，如a|b代表同时过滤a和b()分组过滤，()中的内容表示一个整体，如(abc)表示过滤abca{m,n}匹配a最少m次，最多n次；如a{3,5}代表匹配a最少3次，最多5次`a{m,}匹配a最少m次；如a{3,}代表匹配a最少3次，没有上限a{,n}匹配a最少0次，最多n次；如a{,5}代表匹配a最少0次，最多5次a{n}匹配a正好n次；如a{5}代表匹配a 5次ERE拓展指令之 ()小括号，将一个或者多个字符捆绑在一起，当做一个整体处理功能一 分组过滤被括起来的内容,括号内的内容是一个整体功能二 括号中的内容还可以被后面的\n引用，n代表数字，表示引用第几个括号的内容示例： `\1` 表示从左侧开始,第一个括号中的模式所匹配到的字符 `\2` 表示从左侧开始,第二个括号模式所匹配的字符BRE的使用1. 列出 包含 "root" 的行及行号 grep -n "root" demo.txt 2. 列出包含 "ROOT" 的行及行号 grep -n "ROOT" demo.txt 3. 列出包含 root [不区分大小写]的行及行号 grep -n -i "root" demo.txt 4. 列出不包含 "root"[无论大小写] 的行及行号 grep -n -i -v "root" demo.txt 5. 列出包含 root 或者 love 的行及 行号 grep -n "root|love" demo.txt # 这条命令会无输出，因为`|`属于ERE,必须使用 grep -E grep -n -E "root|love" demo.txt # 这条才是正确的命令 6. 列出 root 单词所在的行 grep -n -w "root" demo.txt 7. 使用 grep 列出所有文件内容 grep -n ".*" demo.txt 8. 列出注释行 grep -n "^#" demo.txt 9. 列出空白行 grep -n "^$" demo.txt 10. 列出所有的注释行和空白行 grep -n -E "^#|^$" demo.txt 11. 排除所有的注释行和空行 grep -n -E -v "^#|^$" demo.txt 12. 列出所有以 . 结尾的行 grep -n "\.$" demo.txtBRE的演示1. 获取 demo.txt中所有以 H 开头的行 grep -n "^H" demo.txt 2. 获取demo.txt 中所有以 i 开头的行 grep -n "^i" demo.txt grep -n -i "^i" demo.txt # 忽略匹配规则字符的大小写 3. 获取文件中以 n 结尾的行 grep -n "n$" demo.txt 4. 获取文件中以 . 结尾的行 grep -n "\.$" demo.txt 5. 获取文件中的空行及行号 grep -n "^$" demo.txt 6. 获取文件中非空行以及行号 grep -n -v "^$" demo.txt grep -n -i "." demo.txt 7. 匹配模式是三位字符,其中后两位是 nu 第一位任意 grep -n ".nu" demo.txt 8. 匹配模式是三位字符 其中中间是任意字符 两边是 f h grep -n "f.h" demo.txt 9. 匹配模式为 每行 不区分大小写的 i 出现 0 ~ n次 grep -n -i "i*" demo.txt 10. 获取所有文件内容 grep -n ".*" demo.txt 11. 匹配模式为 左侧为 I 右侧为 o 中间任意次数的任意字符 grep -n "I.*o" demo.txt 12. 匹配模式为 出现 a b c 任意一个字符 grep -n "[abc]" demo.txt 13. 匹配模式为 未出现 a b c 的任意字符 grep -n -v "[abc]" demo.txt 14. 匹配非abc内容 grep -n -v "abc" demo.txt 15. 匹配除了字符a b c的内容 grep -n "[^abc]" demo.txt # 全选所有字符，除了a b c 16. 匹配不包含字符a b c的行 grep -n -i -v "[abc]" demo.txt 16. 匹配模式为 出现 a ~ k 之间任意一个字符 grep -n "[a-k]" demo.txt 17. 匹配模式为 出现 字母的行 grep -n -i "[a-z]" demo.txt grep -n "[a-zA-Z]" demo.txt 18. 匹配所有数字的行 grep -n "[0-9]" demo.txt 19. 匹配所有数字 所有字母 grep -n "[0-9a-zA-Z]" demo.txt grep -n -i "[0-9a-z]" demo.txtERE的演示1. 找出文件中包含 loe 或者 le 的行 grep -E -n "lo?e" demo.txt grep -n -E "loe|le" demo.txt 2. 找出文件中出现 1 ~ n 次 l 的行 grep -E -n "l+" demo.txt 3. 获取文件中出现字符 a 或者 字符 b 的行 grep -n "[ab]" demo.txt grep -n -E "a|b" demo.txt 4. 获取根目录下 所有 名字中包含 a 或者 b的 .txt 文件 find / -type f -name "*.txt" | grep -E "a|b" find ./ -type f -name "*.txt" | grep -E '[^/]*[ab][^/]*\.txt$' # 严格来说这个应该是对的，只匹配文件名包含a或b的文件， # 如果使用上一条命令，会存在路径中包含a或b， # 但是文件名不包含a或b的错误结果 5. 获取文件中的good glad grep -n -E "good|glad" ok.log grep -n -E "g(oo|la)d" ok.log 6. （l..e）匹配l在左侧，e在右侧，中间是任意两个字符：(l..e) ... (l..e) grep -n -E "(l..e).*\1" ok.log # \1 代表引用前面（）的结果 7. 匹配字母a 最少 1次 最多 3次 grep -E "a{1,3}" demo3.txt # 即使HHDwhdhnaaaaaaaaaaaaaaa这样的结果也是 正确的， # 因为a{1,3} 表示：连续 1 到 3 个 a。 # 只要某个子串满足这个条件，整行都会被匹配出来。 # 所以 "HHDwhdhnaaaaaaaaaaaaaaa" 中， # 任意一段连续的 1~3 个 a（比如 "aaa" 或 "aa" 或 "a"）都满足条件。 8. 匹配字母a 最少 2 次 最多 3次 grep -E -o "a{2,3}" demo3.txt 9. 逐行匹配字母a 最少 4次 grep -E -o "a{4,}" demo3.txt 10. 逐行匹配字母a 最多4次 grep -E "a{,4}" demo3.txt 11. 逐行匹配字母a 恰好4次 grep -E -o "a{4}" demo3.txtLinux文本三剑客grepsedsed 流编辑器，Stream Editor操作、过滤、转换文本内容用法：sed [参数] [匹配模式/内置命令] 文件 参数介绍： -n 取消默认sed的输出，常与sed内置命令p一起用，不加-n则会输出一遍原始文件 -i 直接将修改结果写入文件, 未使用-i，sed修改的只是内存数据(对文件数据没有影响) -e 多次编辑,不需要管道符 -r 支持扩展正则表达式 内置命令：用于对文件进行不同的操作,例如 增加,删除,修改,查询打印文件信息 a append,对文本追加,在指定行`后面添加`一行或者多行文本 d delete,删除匹配的行 i insert 表示插入文本,在指定行`之前添加`一行或者多行文本 p print 打印匹配行的内容 通常与参数`-n`一起用 s/正则表达式/替换内容/g 或者 s#正则表达式#替换内容#g 批量替换内容 示例： 1. sed打印第2~5行的内容 sed -n '2,5p' ok.log 2. sed匹配并输出linux字符串 sed -n '/linux/p' ok.log 3. 删除games字符串的行 sed -n '/games/d' ok.log 4. 将文件中所有的a替换为g sed -n -i 's/a/g/g' ok.log 5. 替换所有hes为my，同时把qq替换为88888888 sed -i -e 's/hes/my/g' -e 's/qq/88888888/g' 6. 在文件第二行追加内容并写入文件 sed -i '2a hello world' ok.log 7. 在文件第二行追加两行内容 sed -i '2a hello world \nnihaozhangsan' ok.log 8. 在文件每一行后都添加新内容 sed -i 'a ---测试---' ok.log 9. 删除每一行的内容 sed -i 'd' ok.log 10. 删除第2行的内容 sed -i '2d' ok.log 11. 删除第2~5行的内容 sed -i '2,5d' ok.log 12. 删除第2、5行的内容 sed -i -e '2d' -e '5d' ok.log 13. 删除第2~最后一行的内容 sed -i '2,$d' ok.log 14. 过滤ip地址所在的行 ip a | sed -n '9p' # 9p是指定第9行（ens160）网卡的IP 15. 只保留ip地址 ip a | sed -n '9p' | sed -e 's/.*inet.//g' -e 's/\/24.*//g' # inet 192.168.119.20/24 brd 192.168.119.255 scope global noprefixroute ens160 # 删除inet包括前后的空格：s/.*inet.//g # 删除网段号/24及以后的内容：s/\/24.*//g # 这样写也是可以的：s#/24.*##gawkawk可以进行文本的格式化。 ---- 将文本数据格式化为专业的excel表样式 awk早期在Unix系统中使用,我们使用的 awk 实际是 gawk GUN awk。 awk也是一门编程语言，支持条件判断、数组、循环 用法：awk 可选参数 模式 {动作} 文件(或者数据) 注意： - 动作主要是指数据的"格式"化 ---- 最常用的动作 print 和 printf - awk默认的空格就是分隔符,且多个空格也会识别为一个空格并作为分隔符 - awk按行处理，一行处理完毕,再处理下一行；根据用户指定的分隔符去工作，没有指定分隔符默认使用空格 - 指定了分隔符，awk把每一行切割后的数据对应到内置变量中 参数介绍： -F 指定输入分隔符 -v 定义或修改内置变量 -f 从脚本文件读取awk指令 内置变量： $n 输出第几列，默认以空格分割 $0 完整的输入记录，即输出全部内容，个人理解是$0表示一整行内容 FS 输入字段分隔符,默认是空格 OFS 输出字段分隔符 默认是 空格 NF 分割后,当前行一共有多少列 $NF 表示当前分割的最后一列 $(NF-1) 表示分割后倒数第二列 NR 当前记录数 ---- 多少行 2 输出2 示例： 1. 查看ok.log的内容 awk '{print $0}' ok.log 2. 查看第二列的内容 awk '{print $2}' ok.log 3. 查看第1、2、3列的内容 awk '{print $1,$2,$3}' ok.log 3. 查看第1、2、3列的内容，格式化输出 awk '{print "第一行：",$1,"第二行：",$2,"第三行：",$3}' ok.log 4. 打印3，有几行就打印几个 awk '{print 3}' ok.log # 输出结果如下所示：如果有100行，就打印100行3，每行一个 # 3 # 3 # 3 # 3 # 3 # 3 # 3 5. 查看文件有多少行 awk '{print NR}' ok.log 6. 给每一行添加行号 awk '{print NR,$0}' ok.log 6. 查看文件每行有几列 awk '{print NF}' ok.log 7. 查看文件最后一列 awk '{print $NF}' ok.log 8. 查看文件倒数第二列 awk '{print $(NF-1)}' ok.log 9. 输出第五行 注意： NR==5 一个等号是赋值的含义 两个等号才是关系运算符 awk 'NR==5' ok.log 10. 输出第2~5行 awk 'NR==2,NR==5' ok.log 11. 指定分隔符 : ,获取用户名和UID awk -F : '{print $1,$3}' /etc/passwd awk -v FS=: '{print $1,$3}' /etc/passwd 使用正则表达式 1. 指定输出分隔符 # ,分隔用户名和UID awk -v FS=: -v OFS=# '{print $1,$3}' /etc/passwd 2. 获取以root开头的行并输出 awk '/^root/{print $0}' /etc/passwd 3. 获取以root开头的行并输出UID awk -F : '/^root/{print $3}' /etc/passwd 4. 获取禁止登陆的用户信息 awk '/\/sbin\/nologin$/{print $0}' /etc/passwd 5. 获取禁止登录的用户的用户名 awk -F : '/\/sbin\/nologin$/{print $1}' /etc/passwd 6. 获取禁止登录的用户的用户名和UID，格式化输出 awk -F : '/\/sbin\/nologin$/{print "用户名：",$1,"\t UID：",$3}' /etc/passwd awk -F : '/\/sbin\/nologin$/{printf "用户名：%-10s\t,UID：%-10s\n",$1,$3}' /etc/passwd # 这条指令用的C风格输出 Ansible目标机器安装控制中心的ssh公钥安装ansible的方式pip安装 pip install ansibleyum安装 yum install ansible源码安装docker安装配置工作目录ansible_quickstart mkdir ansible_quickstart && cd ansible_quickstart创建配置清单inventory.ini vi inventory.ini添加myhosts组,指定目标机器的ip或域名，[myhosts] 192.0.2.50 192.0.2.51 192.0.2.52验证配置文件是否正确 ansible-inventory -i inventory.ini --listping测试ip或域名是否可用 ansible myhosts -m ping -i inventory.ini根据规模需求选择ini或者yml配置文件ini[myhosts] 192.0.2.50 192.0.2.51 192.0.2.52yamlmyhosts: hosts: my_host_01: ansible_host: 192.0.2.50 my_host_02: ansible_host: 192.0.2.51 my_host_03: ansible_host: 192.0.2.52集群主机分组技巧拓扑结构分组地理位置分组按照开发阶段分组创建元组 metagroupname: children:示例： leafs: hosts: leaf01: ansible_host: 192.0.2.100 leaf02: ansible_host: 192.0.2.110 spines: hosts: spine01: ansible_host: 192.0.2.120 spine02: ansible_host: 192.0.2.130 network: children: leafs: spines: webservers: hosts: webserver01: ansible_host: 192.0.2.140 webserver02: ansible_host: 192.0.2.150 datacenter: children: network: webservers:局部变量webservers: hosts: webserver01: ansible_host: 192.0.2.140 http_port: 80 webserver02: ansible_host: 192.0.2.150 http_port: 443全局变量webservers: hosts: webserver01: ansible_host: 192.0.2.140 http_port: 80 webserver02: ansible_host: 192.0.2.150 http_port: 443 vars: ansible_user: my_server_user剧本创建剧本playbook.yml- name: My first play hosts: myhosts tasks: - name: Ping my hosts ansible.builtin.ping: - name: Print message ansible.builtin.debug: msg: Hello world运行剧本ansible-playbook -i inventory.ini playbook.yamlPython更新pippython -m pip install --upgrade pipNginx官网： http://www.nginx.org 链接： https://nginx.org/download/nginx-1.24.0.tar.gz 参数与使用 用法： 参数介绍： 示例：源码编译安装准备工作获取源码包链接编译环境准备 gcc make编译环境准备yum -y install gcc make zlib-devel pcre pcre-devel openssl-devel软件介绍 gcc 是编译工具,编译单个文件make 工具是一个只能得批处理工具,通过makefile 文件中用户指定的命令来进行编译(将高级语言写的代码编译成二进制语言)pcre 支持正则表达式zlib-devel 有些应用依赖于这个库openssl-devel 某些库文件跟开发有关获取nginx的压缩安装包(二选一即可)wget [-O 源码包保存目录并重命名] https://nginx.org/download/nginx-1.24.0.tar.gzcurl -o 源码包保存目录并重命名 https://nginx.org/download/nginx-1.24.0.tar.gz解压缩获取的安装包tar -zxvf nginx.tar.gz 得到一个文件夹 nginx-1.24.0切换进nginx-1.24.0文件夹cd nginx-1.24.0执行内部指令(内部指令必须使用相对或者绝对路径选中)./configure --user=alex --group=alex --prefix=/usr/local/nginx说明: --user 指定用户 --group 指定用户组 --prefix 指定安装路径编译文件make安装文件make install若指定的用户不存在-----执行新建用户,默认会构建一个同名的主属组useradd alex关闭防火墙systemctl stop firewalld启动nginx/usr/local/nginx/sbin/nginx使用结束以后关闭nginx/usr/local/nginx/sbin/nginx -s stopLAMP架构LAMP：Linux + Apache + MySQL + PHP LAMP 架构（组合）LNMP：Linux + Nginx + MySQL + php-fpm LNMP 架构（组合）LNMPA：Linux + Nginx(80) + MySQL + PHP + Apache Nginx 代理方式 Apache：Apache是世界使用排名第一的Web服务器软件。 PHP：一种专门用于Web开发的编程语言。 MySQL：MySQL是一个关系型数据库管理系统，主要用于永久存储项目数据。AMP三者之间的关系Apache：用于接收用户的请求（输入网址，返回网页=>结果）PHP：注册、登录、加入购物车、下单、支付等动态功能（有编程语言的支持）MySQL：永久保存数据，比如你在网站上注册的用户和密码、你加入购物车的产品、你的产品订单LAMP环境安装Apache安装配置文件：/etc/httpd/conf/httpd.conf项目目录：/var/www/html安装apache yum install httpd修改端口（可选）# vim /etc/httpd/conf/httpd.conf # 搜索ServerName：/ServerName ServerName localhost:80设置开机自启动systemctl status httpd # 查看当前运行状态 systemctl start httpd # 启动httpd systemctl stop httpd # 关闭httpd systemctl enable httpd # 打开开机自启 systemctl disable httpd # 取消开机自启访问测试 打开浏览器，访问http://localhost:80/，观察是否能进入测试页面Mysql安装安装mysql源wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm rpm -ivh mysql-community-release-el7-5.noarch.rpm安装mysql yum install mysql-community-server设置开机自启动systemctl status mysqld # 查看当前运行状态 systemctl start mysqld # 启动mysqld systemctl stop mysqld # 关闭mysqld systemctl enable mysqld # 打开开机自启 systemctl disable mysqld # 取消开机自启初始化mysql默认情况下，数据库没有密码，也没有任何数据，必须要初始化初始化数据，设置root密码（MySQL管理员） mysql_secure_installation 注意：以上说的root和Linux中的root不是同一个用户，这个root代表MySQL数据库的管理员，只不过这个管理员也叫root。 访问测试 打开终端，输入mysql -u root -p，回车，输入密码，查看是否能成功登录Php安装安装php yum install php重启apachesystemctl stop httpd # 关闭httpd systemctl start httpd # 启动httpd测试phpapache项目目录：/var/www/html打开项目目录 cd /var/www/html创建demo.php vi demo.php在demo.php中输入php代码并保存<?php echo 'hello 帅辉'; ?>访问测试 打开浏览器，输入http://localhost:80/demp.php，测试能否成功看到 "hello 帅辉"实战：部署Discuz！论坛升级php到7.4更新php源： yum -y install https://rpms.remirepo.net/enterprise/remi-release-7.rpm启用PHP 7.4 Remi仓库yum -y install yum-utils yum-config-manager --enable remi-php74安装新版本php和拓展包 yum install php php-cli php-fpm php-mysqlnd php-zip php-devel php-gd php-mcrypt php-mbstring php-curl php-xml php-pear php-bcmath php-json测试php是否更新 php -v查看版本php -v PHP 7.4.33 (cli) (built: Jun 5 2024 05:05:14) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies开始安装Discuz下载界面下载链接下载Discuz到/var/www/html目录下 wget https://gitee.com/Discuz/DiscuzX/attach_files/2044572/download会得到一个Discuz_X3.5_SC_UTF8_20250205.zip的压缩包。解压安装包 unzip Discuz_X3.5_SC_UTF8_20250205.zip 解压到当前目录删除安装包 rm -rf Discuz_X3.5_SC_UTF8_20250205.zip设置权限 为/var/www/html增加写权限 chmod -R o+w /var/www/html重启http服务器systemctl stop httpd # 关闭httpd systemctl start httpd # 启动httpd安装部署 打开浏览器，输入http://localhost:80/upload，开始安装帮助指令man 查看所有帮助手册指令 --help 查看指令的用法帮助RHEL重置root密码重启Linux，进入内核选择界面，按下e，进入内核编辑模式在启动参数后添加rd.break参数，按下Ctrl^X执行修改过的程序等待系统进入救援模式，挂载系统分区。mount -o remount,rw /sysroot chroot /sysroot passwd touch /.autorelabel exit reboot附件Linux目录树原始Markdown+ / + boot 存放系统内核与启动文件 + dev 存放硬件设备相关信息 + etc 存放系统配置文件 - resolv.conf 设置域名解析 - hostname 设置主机名 - motd 设置开机提示语 - os-release 查看发行版和版本号 + sysconfig + network-scripts - ifconfig-xxx 设置网络环境，如动态IP等 + home 普通用户的主目录 + media 可卸载的存储介质挂载点 + mnt mount文件的临时挂载点 + opt 应用程序包的安装目录 + proc 系统内存的映射目录，提供内核与进程信息 + root 特权用户目录 + run 存放组件运行时所需文件[文件夹] + srv 存放组件运行时所需文件 + temp 存放临时文件 + usr 存放用户程序 + var 存放运行时内容会改变的文件，如日志等
首先获取hostname：hostname然后编辑/etc/hosts文件，加入以下内容：127.0.0.1 localhost 你的hostname
如果zip文件是GB2312编码的，在Linux下直接unzip 文件.zip就会解压出乱码文件。可以加上神秘的-O选项指定编码解压。示例：unzip -O GB2312 ./office字体.zip
mount命令挂载磁盘的时候加上-o iocharset=编码选项即可。示例：mount /dev/sdb /mnt/usb -o iocharset=utf8
LXQt配置中心 => 会话配置 => 环境添加变量名如下QT_AUTO_SCREEN_SCALE_FACTOR=2 XCURSOR_SIZE=24
有些时候，如项目进行编译的时候，会受到Windows长路径的限制，进而产生编译失败。可以进入Windows系统策略设置，更改“启用 Win32 长路径（Enable Win32 long paths）”状态，这样就可以不限最长路径（MAX_PATH）限制。启用方法： win + r 打开运行，键入gpedit.msc，找到计算机配置->管理模板->系统->文件系统->启用win32长路径,双击，把选项改为已开启即可。
Android权限申请权限详细的权限文档请参考：Android 权限文档权限的申请方式1. 动态申请动态申请需要在代码中调用ActivityCompat.requestPermissions方法，该方法有三个参数：Context上下文，要申请的权限，请求码申请SD卡写权限示例：ActivityCompat.requestPermissions(MainActivity.this, new String[] {"android.permission.WRITE_EXTERNAL_STORAGE"}, 1);2. 静态申请在AndroidManifest.xml的<manifest>标签中使用<uses-permission>标签来实现静态获取权限。需要注意的是，在Android6.0以后，Android修改了权限申请机制，其将权限分为了正常权限和危险权限两大类。申请危险权限时不仅要在AndroidManifest.xml中静态申请权限，还要在代码里动态申请权限。2.1 正常权限：不会直接给用户带来隐私风险的权限，如请求网络的权限。2.2 危险权限：涉及用户隐私的权限。申请该权限的应用程序，可能涉及用户隐私信息的数据或资源，也可能对用户存储的数据或其他应用程序的操作产生影响。危险权限一共有九组：位置（LOCATION）日历（CALENDAR）照相机（CAMERA）联系人（CONTACTS）存储卡（STORAGE）传感器（SENSORS）麦克风（MICROPHONE）电话（PHONE）短信（SMS）静态权限申请示例：<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mkirin.musicplayer"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> </manifest>