├── README.md ├── .gitignore ├── loppo.yml ├── chapters.yml ├── docs ├── hardware.md ├── distro │ ├── fedora.md │ └── arch.md ├── intro.md ├── systemd.md ├── file-system.md ├── user.md ├── xargs.md └── cron.md ├── package.json └── .github └── workflows └── wangdoc.yml /README.md: -------------------------------------------------------------------------------- 1 | Linux 教程,正在建设中,目前还是笔记状态。 2 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | package-lock.json 4 | 5 | -------------------------------------------------------------------------------- /loppo.yml: -------------------------------------------------------------------------------- 1 | dir: docs 2 | output: dist 3 | site: Linux 教程 4 | theme: wangdoc 5 | customization: false 6 | themeDir: loppo-theme 7 | direction: ltr 8 | id: linux 9 | branch: main 10 | hasComments: true 11 | isTutorial: true 12 | 13 | -------------------------------------------------------------------------------- /chapters.yml: -------------------------------------------------------------------------------- 1 | - intro.md: Linux 介绍 2 | - user.md: 用户管理 3 | - file-system.md: 文件系统 4 | - cron.md: Cron 定时任务 5 | - systemd.md: SystemD 6 | - hardware.md: 硬件管理 7 | - xargs.md: xargs 命令 8 | - distro/: 发行版 9 | - distro/arch.md: Arch Linux 10 | - distro/fedora.md: Fedora 11 | -------------------------------------------------------------------------------- /docs/hardware.md: -------------------------------------------------------------------------------- 1 | # Linux 硬件管理 2 | 3 | ## 挂载外部硬盘 4 | 5 | 系统接入外部硬盘后,先用 fdisk 命令找出硬盘编号。 6 | 7 | ```bash 8 | $ sudo fdisk -l 9 | ``` 10 | 11 | 这里假定硬盘编号是`/dev/sdc`。 12 | 13 | 然后,创建一个挂载点目录`/mnt/sdd`。 14 | 15 | ```bash 16 | $ sudo mkdir /mnt/sdd 17 | ``` 18 | 19 | 接着,使用 mount 命令将外部硬盘挂载到该目录。 20 | 21 | ```bash 22 | $ sudo mount /dev/sdc /mnt/sdc 23 | ``` 24 | 25 | 如果挂载的硬盘为 NTFS 格式,需要用 mount 命令的`-t`参数指定挂载类型。 26 | 27 | ```bash 28 | # 只读 29 | $ sudo mount -t ntfs /dev/sdc /mnt/sdc 30 | 31 | # 读写 32 | $ sudo mount -t ntfs-3g /dev/sdc /mnt/sdc 33 | ``` 34 | 35 | 最后,使用 df 命令查看是否挂载成功。 36 | 37 | ```bash 38 | $ df -h 39 | ``` 40 | 41 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "linux-tutorial", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "directories": { 6 | "doc": "docs" 7 | }, 8 | "scripts": { 9 | "build": "loppo --site \"Linux 教程\" --id linux --theme wangdoc", 10 | "build-and-commit": "npm run build && npm run commit", 11 | "commit": "gh-pages --dist dist --dest dist/linux --branch master --repo git@github.com:wangdoc/website.git", 12 | "chapter": "loppo chapter", 13 | "server": "loppo server" 14 | }, 15 | "keywords": [ 16 | "wangdoc", 17 | "document", 18 | "linux" 19 | ], 20 | "author": "Ruan Yifeng", 21 | "license": "CC-BY-SA-4.0", 22 | "description": "", 23 | "dependencies": { 24 | "gh-pages": "^6.1.1", 25 | "loppo": "^0.6.26", 26 | "loppo-theme-wangdoc": "^0.7.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /docs/distro/fedora.md: -------------------------------------------------------------------------------- 1 | # Fedora 2 | 3 | ## 包管理器 dnf 4 | 5 | Fedora 的包管理器基于 rpm,并在其上构建了几个更高级别的工具,最著名的是 PackageKit(默认 gui)和 DNF。GNOME Software 也可以用。 6 | 7 | DNF 现在是 Fedora 默认的包管理器。 8 | 9 | ```bash 10 | # 搜索 11 | $ sudo dnf search 包名 12 | 13 | # 安装 14 | $ sudo dnf install 包名 15 | 16 | # 删除 17 | $ sudo dnf remove 包名 18 | ``` 19 | 20 | 更新系统。 21 | 22 | ```bash 23 | $ sudo dnf upgrade --refresh -y 24 | ``` 25 | 26 | dnf 的其他命令如下。 27 | 28 | - autoremove- 删除所有不再需要的软件包。 29 | - check-update- 检查更新,但不下载或安装软件包。 30 | - downgrade- 恢复到以前版本的包。 31 | - info- 提供有关包的基本信息,包括名称、版本、版本和描述。 32 | - reinstall- 重新安装当前安装的包。 33 | - upgrade- 检查更新包的存储库并更新它们。 34 | - exclude- 从交易中排除包裹。 35 | 36 | dnf 可用来在命令行直接升级 Fedora,参考[官方文档](https://docs.fedoraproject.org/en-US/quick-docs/dnf-system-upgrade/)。 37 | 38 | 安装语言包 39 | 40 | ```bash 41 | $ sudo dnf install langpacks-zh_CN 42 | ``` 43 | 44 | -------------------------------------------------------------------------------- /docs/intro.md: -------------------------------------------------------------------------------- 1 | # Linux 介绍 2 | 3 | ## 查看系统信息 4 | 5 | (1)`/etc/os-release`文件 6 | 7 | `/etc/os-release`文件包含当前系统的标识数据和发行信息,查看此文件可以了解当前系统的发行版信息。 8 | 9 | ```bash 10 | $ cat /etc/os-release 11 | ``` 12 | 13 | 这个文件包含在 SystemD 软件包,只要当前发行版使用 SystemD,一般就会包含这个文件。 14 | 15 | RedHat 相关发行版还会有`/etc/redhat-release`文件。 16 | 17 | (2)`/etc/issue`文件 18 | 19 | `/etc/issue`文件也会包含当前系统的版本名称。 20 | 21 | ```bash 22 | $ cat /etc/issue 23 | ``` 24 | 25 | (3)`hostnamectl`命令 26 | 27 | `hostnamectl`命令用于查找和更改系统主机名,也可以用它显示当前系统的版本信息。 28 | 29 | ```bash 30 | $ hostnamectl 31 | ``` 32 | 33 | (4)`uname`命令 34 | 35 | `uname`命令可以显示系统信息,包含 Linux 内核架构、名称、发布版。 36 | 37 | ```bash 38 | # 所有信息 39 | $ uname -a 40 | 41 | # 操作系统 42 | $ uname -o 43 | 44 | # 内核版本 45 | $ uname -r 46 | ``` 47 | 48 | (5)`lsb-release`命令 49 | 50 | 如果系统安装了`lsb-release`软件包,就可以用`lsb-release`命令查看当前系统的发行版。 51 | 52 | ```bash 53 | $ lsb-release 54 | ``` 55 | 56 | (6)`/proc/version`文件 57 | 58 | `/proc/version`文件也包含了内核和版本信息。 59 | 60 | ```bash 61 | $ cat /proc/version 62 | ``` 63 | 64 | -------------------------------------------------------------------------------- /.github/workflows/wangdoc.yml: -------------------------------------------------------------------------------- 1 | name: Linux tutorial CI 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | page-generator: 9 | name: Generating pages 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | with: 15 | persist-credentials: false 16 | - name: Setup Node.js 17 | uses: actions/setup-node@v4 18 | with: 19 | node-version: 'latest' 20 | - name: Install dependencies 21 | run: npm install 22 | - name: Build pages 23 | run: npm run build 24 | - name: Deploy to website 25 | uses: JamesIves/github-pages-deploy-action@v4 26 | with: 27 | git-config-name: wangdoc-bot 28 | git-config-email: yifeng.ruan@gmail.com 29 | repository-name: wangdoc/website 30 | token: ${{ secrets.WANGDOC_BOT_TOKEN }} 31 | branch: master # The branch the action should deploy to. 32 | folder: dist # The folder the action should deploy. 33 | target-folder: dist/linux 34 | clean: true # Automatically remove deleted files from the deploy branch 35 | commit-message: update from Linux tutorial 36 | 37 | -------------------------------------------------------------------------------- /docs/systemd.md: -------------------------------------------------------------------------------- 1 | # SystemD 2 | 3 | ## 简介 4 | 5 | SystemD 是 Linux 的系统管理器,它的主要接口是 systemctl(即用户执行的命令)。 6 | 7 | 通过 systemctl 接口,可以启动/停止“单元”(unit),最常用的单元是“服务单元”(service),即系统守护程序。其他单元还有套接字单元(network socket)、定时器单元(timer)等等。 8 | 9 | 服务单元会有一个服务描述文件,里面设置启动该服务需要知道的信息,比如 sshd 的服务描述是“在多用户模式下,等待网络可用后,运行 SSH 服务器。” 修改服务描述文件以后,必须重新启动服务,修改才会生效。 10 | 11 | ## 服务描述文件 12 | 13 | 下面是一个服务描述文件的示例。它有很多设置,但是常用的就是那么几个。 14 | 15 | ```bash 16 | [Unit] 17 | Description=OpenBSD Secure Shell server 18 | Documentation=man:sshd(8) man:sshd_config(5) 19 | After=network.target auditd.service 20 | ConditionPathExists=!/etc/ssh/sshd_not_to_be_run 21 | 22 | [Service] 23 | EnvironmentFile=-/etc/default/ssh 24 | ExecStartPre=/usr/sbin/sshd -t 25 | ExecStart=/usr/sbin/sshd -D $SSHD_OPTS 26 | ExecReload=/usr/sbin/sshd -t 27 | ExecReload=/bin/kill -HUP $MAINPID 28 | KillMode=process 29 | Restart=on-failure 30 | RestartPreventExitStatus=255 31 | Type=notify 32 | RuntimeDirectory=sshd 33 | RuntimeDirectoryMode=0755 34 | 35 | [Install] 36 | WantedBy=multi-user.target 37 | Alias=sshd.service 38 | ``` 39 | 40 | 网上有一些[描述文件生成器](https://mysystemd.talos.sh/),可以使用。 41 | 42 | 系统的单元描述文件,一般放在目录`/etc/systemd/system`。用户的单元描述文件放在目录`/etc/systemd/user`。命令`systemctl status xxx.service`会显示单元描述文件的位置。 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /docs/file-system.md: -------------------------------------------------------------------------------- 1 | # Linux 文件系统 2 | 3 | 文件系统指的是 Linux 内部的文件布局。 4 | 5 | 任何 Linux 系统,顶部总是一个根目录,写成`/`,其他目录都是根目录的子目录。下面就是根目录下的一些主要的子目录。 6 | 7 | `/root`是根用户的主目录,根用户的文件都会放在这个目录。 8 | 9 | `/home`是其他用户的主目录,每个用户在`/home`下面都会有自己的主目录。比如,用户`ruanyf`的主目录就是`/home/ruanyf`。用户自己的主目录可以用快捷方式`~`或`$HOME`访问。每个用户只能打开自己的主目录,不能访问其他用户的子目录。 10 | 11 | `/bin`和`sbin`这两个目录,都包含应用程序和可执行命令的二进制文件。区别是`/bin`包含系统基本操作所需的二进制文件(例如 ls、cp、mv、mkdir 等命令),而`/sbin`包含管理系统所需的二进制文件(例如 fdisk)。 12 | 13 | `/usr`存放用户自己安装的程序。如果你自己安装了一个程序,它的二进制命令一般会放在`/usr/bin`这个目录,它的库会放在`/usr/lib`目录。 14 | 15 | `/etc`存放系统和应用程序的配置文件。比如,网络配置、用户信息和系统设置都可以在这个目录中找到。 16 | 17 | `/opt`存放系统可选的安装文件。比如,安装了 MS Edge 浏览器,它就会放在`/opt/microsoft`,里面包含了它运行所需的所有库和可执行文件。 18 | 19 | `/lib`包含系统的应用程序所需的所有基本库。 20 | 21 | `/boot`包含引导过程所需的所有文件,包括内核、初始 RAM 磁盘和引导加载程序的配置文件。 22 | 23 | `/media`是磁盘(包括光盘驱动器)的安装和访问位置。如果插入 USB 驱动器,它就会安装在`/media`下面的子目录。 24 | 25 | `/mnt`类似于`/media`,但只用在挂载其他文件系统,比如网络文件系统。 26 | 27 | `/proc`包含进程信息的文件。在这个目录中,你会看到一组有编号的子目录,每个子目录关联一个正在运行的进程,子目录编号就是进程号。 28 | 29 | `/run`包含运行时数据、一些系统日志、进程 ID 和临时文件。 30 | 31 | `/srv`保存各种服务端的数据,例如 Web 和 FTP 服务器,仅当安装了此类服务端时才使用此目录。比如,你启动了 FTP 服务器,可以在此目录中创建一个子目录,存放上传和下载的文件。如果你的电脑不用作服务器,只用作桌面电脑,那么该目录为空。 32 | 33 | `/tmp`存放临时文件(由应用程序创建和使用),系统会定期自动删除里面的文件。 34 | 35 | `/var`存放会不断变化的一些文件,比如系统日志、邮件、Web 服务器的文档根目录。如果系统出现问题,可以查看`/var/log`里面的日志。 36 | 37 | -------------------------------------------------------------------------------- /docs/user.md: -------------------------------------------------------------------------------- 1 | # Linux 的用户管理 2 | 3 | ## 新增用户的一般流程 4 | 5 | 新增用户。 6 | 7 | ```bash 8 | $ useradd -m [username] 9 | $ passwd [username] 10 | ``` 11 | 12 | 将新增的用户加入用户组。 13 | 14 | ```bash 15 | $ usermod -aG wheel,audio,video,storage [username] 16 | ``` 17 | 18 | 为了让新增用户有使用 sudo 命令的权限,需要使用 visudo,打开 sudo 的权限文件(`/etc/sudoers`),取消 wheel 用户组前面的注释。 19 | 20 | ```bash 21 | $ visudo 22 | ``` 23 | 24 | ## 组管理 25 | 26 | `/etc/group`是用户组的定义文件。 27 | 28 | `groups`命令显示用户所属的组。 29 | 30 | ```bash 31 | $ groups [username] 32 | ``` 33 | 34 | 如果省略`username`,则显示当前用户所属的组。 35 | 36 | `id`命令显示指定用户的详细信息,包括用户所属的组。 37 | 38 | ```bash 39 | $ id [username] 40 | ``` 41 | 42 | 下面的命令列出当前系统所有的组。 43 | 44 | ```bash 45 | $ cat /etc/group 46 | ``` 47 | 48 | `groupadd`命令用来创建新组。 49 | 50 | ```bash 51 | $ sudo groupadd [groupName] 52 | ``` 53 | 54 | `gpasswd`命令将用户添加到某个组。 55 | 56 | ```bash 57 | $ sudo gpasswd -a [userName] [groupName] 58 | ``` 59 | 60 | `usermod`命令将用户添加到多个组,多个组之间用逗号分隔。 61 | 62 | ```bash 63 | $ sudo usermod -aG [groupsName] [username] 64 | ``` 65 | 66 | 注意,上面命令中,如果省略`-a`,用户将从未列出的组中被删除,即用户仅属于那些列出的组。 67 | 68 | `gpasswd`也可以从组中删除用户。 69 | 70 | ```bash 71 | $ sudo gpasswd -d [userName] [groupName] 72 | ``` 73 | 74 | `groupmod`命令可以修改组名。 75 | 76 | ```bash 77 | $ sudo groupmod -n [new_group] [old_group] 78 | ``` 79 | 80 | `groupdel`命令用来删除组。 81 | 82 | ```bash 83 | $ sudo groupdel [groupName] 84 | ``` 85 | 86 | -------------------------------------------------------------------------------- /docs/distro/arch.md: -------------------------------------------------------------------------------- 1 | # Arch Linux 2 | 3 | ## 简介 4 | 5 | Arch 是一个滚动更新的发行版,以软件包更新快、数量大而著称。 6 | 7 | 还有很多发行版是基于 Arch 的,比如 Manjaro、EndeavourOS、Garuda Linux。 8 | 9 | ## Pacman 包管理器 10 | 11 | Pacman 是 Arch 的官方包管理器。 12 | 13 | `-Sy`更新软件包列表。 14 | 15 | ```bash 16 | $ sudo pacman -Sy 17 | ``` 18 | 19 | `-Syu`更新当前系统的所有软件包。 20 | 21 | ```bash 22 | $ sudo pacman -Syu 23 | ``` 24 | 25 | `-Ss`用来搜索软件包。 26 | 27 | ```bash 28 | $ sudo pacman -Ss vlc 29 | ``` 30 | 31 | `-Si`用来获取软件包的详细信息。 32 | 33 | ```bash 34 | $ pacman -Si nginx 35 | ``` 36 | 37 | `-S`用来安装软件包。 38 | 39 | ```bash 40 | $ sudo pacman -S vlc 41 | ``` 42 | 43 | `-S`可以一次安装多个包。 44 | 45 | ```bash 46 | $ sudo pacman -S pac1 pac2 47 | ``` 48 | 49 | `-S`也可以用来更新软件包。 50 | 51 | `-Qi`用来查看下载后某个软件包的详细信息。 52 | 53 | ```bash 54 | $ pacman -Qi package 55 | ``` 56 | 57 | `--ignore`指定系统更新时,忽略某个软件包。 58 | 59 | ```bash 60 | $ sudo pacman -Syu --ignore=vlc 61 | ``` 62 | 63 | `-Sw`用来下载某个软件包,但不安装。 64 | 65 | ```bash 66 | $ pacman -Sw vlc 67 | ``` 68 | 69 | `-Q`用来查看系统已经安装的所有软件包。 70 | 71 | ```bash 72 | $ pacman -Q 73 | ``` 74 | 75 | `-Qs`用来搜索某个软件包是否已经安装。 76 | 77 | ```bash 78 | $ pacman -Qs vlc 79 | ``` 80 | 81 | `-Ql`用来查看某个软件包安装的所有文件。 82 | 83 | ```bash 84 | $ pacman -Ql vlc 85 | ``` 86 | 87 | `-Qo`用来查看某个可执行文件属于哪个软件包。 88 | 89 | ```bash 90 | $ pacman -Qo /usr/bin/vlc 91 | ``` 92 | 93 | `-Rs`用来删除指定软件包及其依赖项。 94 | 95 | ```bash 96 | $ sudo pacman -Rs vlc 97 | ``` 98 | 99 | `-Rns`用来删除软件包和配置文件。 100 | 101 | ```bash 102 | $ sudo pacman -Rns vlc 103 | ``` 104 | 105 | 下面的命令用来删除孤儿软件包。 106 | 107 | ```bash 108 | $ sudo pacman -Rns $(pacman -Qdtq) 109 | ``` 110 | 111 | `-U`用来安装本地包。Pacman 将所有下载的包存储在目录`/var/cache/pacman/pkg`,下载以后,可以进入这个目录,安装本地包。 112 | 113 | ```bash 114 | $ cd /var/cache/pacman/pkg/ 115 | $ sudo pacman -U vlc-3.0.11-2-x86_64.pkg.tar.zst 116 | ``` 117 | 118 | `-Sc`用来删除目录`/var/cache/pacman/pkg`里面的软件包缓存。 119 | 120 | ```bash 121 | $ sudo pacman -Sc 122 | ``` 123 | 124 | `-Scc`用来删除缓存目录的所有文件。 125 | 126 | ```bash 127 | $ sudo pacman -Scc 128 | ``` 129 | 130 | ## AUR 软件仓库 131 | 132 | AUR (Arch User Repository)是 Arch 的非官方软件仓库,官方不负责维护,由网友维护。 133 | 134 | 这时可以安装 yay,帮助管理 AUR 软件包。 135 | 136 | ```bash 137 | $ git clone https://aur.archlinux.org/yay-bin.git 138 | $ cd yay-bin 139 | $ makepkg -si 140 | ``` 141 | 142 | 然后,使用下面的命令,查看是否安装成功。 143 | 144 | ```bash 145 | $ yay --version 146 | ``` 147 | 148 | `-S`用来安装软件包。 149 | 150 | ```bash 151 | $ yay -S packageName 152 | ``` 153 | 154 | `-Sua`用来更新所有已经安装的 AUR 软件包。 155 | 156 | ```bash 157 | $ yay -Sua 158 | ``` 159 | 160 | `-Syu`用来更新系统所有软件包。 161 | 162 | ```bash 163 | $ sudo yay -Syu 164 | ``` 165 | 166 | `-Ss`用来搜索软件包,这会同时包括官方仓库和 AUR。 167 | 168 | ```bash 169 | $ yay -Ss packageName 170 | ``` 171 | 172 | 如果只在 AUR 搜索,`-Ss`都不需要。 173 | 174 | ```bash 175 | $ yay packageName 176 | ``` 177 | 178 | `-R`用来删除软件包。 179 | 180 | ```bash 181 | $ yay -R packagename 182 | ``` 183 | 184 | `-Rns`还可以删除依赖项。 185 | 186 | `-Ps`用来查看系统统计信息。AUR 下载所有软包都保存在目录`~/.cache/yay/`。 187 | 188 | ```bash 189 | $ yay -Ps 190 | ``` 191 | 192 | `-Sc`用来清除已经下载的 AUR 文件。 193 | 194 | ```bash 195 | $ yay -Sc 196 | ``` 197 | 198 | `-Scc`用来删除所有不需要的依赖项以及所有缓存的包文件。 199 | 200 | ```bash 201 | $ yay -Scc 202 | ``` 203 | 204 | ## 选择下载镜像 205 | 206 | 软件工具 Reflector 可以选择下载速度最快的软件仓库。 207 | 208 | 它是一个 Python 脚本,会根据下载速度和稳定性,选择对于用户来说最快的下载镜像,然后改写文件`/etc/pacman.d/mirrorlist`。 209 | 210 | 首先,安装这个软件包。 211 | 212 | ```bash 213 | $ sudo pacman -S reflector rsync 214 | ``` 215 | 216 | 然后,备份`/etc/pacman.d/mirrorlist`。不过,这一步不是必需的,因为可以用[在线工具](https://archlinux.org/mirrorlist/)重新创建这个文件。 217 | 218 | ```bash 219 | $ sudo cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.backup 220 | ``` 221 | 222 | 接着,使用 Reflector 找出10个最近同步的下载镜像,按照下载速度排序,并将结果写入`/etc/pacman.d/mirrorlist`。 223 | 224 | ```bash 225 | $ sudo reflector --latest 10 --sort rate --save /etc/pacman.d/mirrorlist 226 | ``` 227 | 228 | 上面命令的几个参数含义如下。 229 | 230 | - `--latest`:筛选范围为最近同步的 n 个服务器。 231 | - `--sort`:按照 rate(下载速度)对镜像进行排序,其他可能的选项是 age、country、score 和 delay。 232 | - `--save`:将结果保存到指定位置。 233 | 234 | 如果要从最近10个同步镜像中选择五个最快的镜像,需要用`--fastest`指定所需的服务器数量。 235 | 236 | ```bash 237 | $ sudo reflector --latest 10 --sort rate --fastest 5 --save /etc/pacman.d/mirrorlist 238 | ``` 239 | 240 | `--list-countries`参数选项可以列出国家地区代码。 241 | 242 | ```bash 243 | $ reflector --list-countries 244 | ``` 245 | 246 | `--country`参数选项可以筛选仅限于指定国家地区的下载镜像。 247 | 248 | ```bash 249 | $ sudo reflector --country "US" --latest 10 --sort rate --save /etc/pacman.d/mirrorlist 250 | ``` 251 | 252 | 上面命令指定下载镜像仅限于美国。 253 | 254 | 如果下载镜像在多个国家地区,可以用逗号分隔。 255 | 256 | ```bash 257 | $ sudo reflector --country "US,CA" --latest 10 --sort rate --save /etc/pacman.d/mirrorlist 258 | # 或者 259 | $ sudo reflector --country "United States,Canada" --latest 10 --sort rate --save /etc/pacman.d/mirrorlist 260 | ``` 261 | 262 | 上面命令将下载镜像限于美国和加拿大。 263 | 264 | `--protocol`参数选项可以指定下载协议:https、http、ftp。它也可以用逗号指定多个协议。 265 | 266 | ```bash 267 | $ sudo reflector --protocol https --latest 10 --sort rate --save /etc/pacman.d/mirrorlist 268 | ``` 269 | 270 | 如果需要 Reflector 定期运行,就需要编辑配置文件`/etc/xdg/reflector/reflector.conf`。编辑完成以后,打开 SystemD 定时器。 271 | 272 | ```bash 273 | $ sudo systemctl enable --now reflector.timer 274 | ``` 275 | 276 | 然后,可以检查一下,定时器是否添加成功。 277 | 278 | ```bash 279 | $ sudo systemctl list-timers 280 | ``` 281 | 282 | 另一种方法是将 Reflector 服务在系统启动时打开。 283 | 284 | ```bash 285 | $ sudo systemctl enable --now reflector.service 286 | ``` 287 | 288 | ## 参考链接 289 | 290 | - [Finding the Most Up-to-Date and Fastest Arch Linux Mirrors](https://linuxiac.com/how-to-find-fastest-arch-linux-mirror/) 291 | -------------------------------------------------------------------------------- /docs/xargs.md: -------------------------------------------------------------------------------- 1 | # xargs 命令 2 | 3 | ## 简介 4 | 5 | xargs 用于将标准输入(stdin),转成其后命令的字符串参数。它通常跟管道命令(`|`)结合使用。 6 | 7 | ```bash 8 | $ {{command1}} | xargs {{command2}} 9 | ``` 10 | 11 | 上面是 xargs 的用法。正常情况下,第一个命令`command1`会输出结果到控制台(即标准输出`stdout`),但是管道命令(`|`)会拦截`command1`的标准输出,将其转为后面命令的标准输入(`stdin`),即`xargs`命令会接收到标准输入,它再将其转为`command2`的字符串参数来运行。 12 | 13 | 举例来说,文本文件`list.txt`的内容是一组文件名。 14 | 15 | ```bash 16 | a.txt 17 | b.txt 18 | c.txt 19 | ``` 20 | 21 | 然后,执行下面的命令,会将这组文件全部删除。 22 | 23 | ```bash 24 | # 删除 a.txt b.txt c.txt 25 | $ cat list.txt | xargs rm 26 | ``` 27 | 28 | 上面示例中,`cat`命令将`list.txt`的内容输出到标准输出,但是被管道命令拦截,转为`xargs`的标准输入,后者再将标准输入转成`rm`命令的字符串参数,即实际执行的是下面的命令。 29 | 30 | ```bash 31 | $ rm a.txt b.txt c.txt 32 | ``` 33 | 34 | 通常来说,Linux 命令分成两种,一种接受标准输入(一般是键盘)作为参数,另一种接受命令行的字符串作为参数。这两种参数的性质有很大的不同:标准输入(stdin)是文本流(stream),理论上只要不终止,就是无限的;命令行参数则是一个有固定长度的文本数组。xargs 的 作用就是接受标准输入,将其转成命令行参数。 35 | 36 | xargs 有点像 echo 命令的逆操作。echo 命令是将命令行参数转为标准输出。 37 | 38 | ```bash 39 | $ echo abc 40 | ``` 41 | 42 | 上面命令中,`abc`是命令行参数,`echo`命令将其转为标准输入。 43 | 44 | 至于管道命令`|`,则是将前一个命令的标准输出,转成后一个命令的标准输入。但是,大多数命令只接受命令行参数,所以管道命令就需要 跟 xargs 结合使用,这是 Linux 的常见操作。 45 | 46 | ## xargs 的单独使用 47 | 48 | xargs 命令也可以单独使用,这时等同于执行`xargs echo`。 49 | 50 | ```bash 51 | $ xargs 52 | # 等同于 53 | $ xargs echo 54 | ``` 55 | 56 | 输入`xargs`后按下回车,命令行就会等待标准输入(即用户的键盘输入)。你可以输入任意内容,然后按下 Ctrl+d,表示输入结束,这时`echo`命令就会把前面的输入打印出来。 57 | 58 | ```bash 59 | $ xargs 60 | hello (Ctrl + d) 61 | hello 62 | ``` 63 | 64 | 上面示例中,执行`xargs`后,从键盘输入`hello`,然后按下 Ctrl+d,就会自动执行`echo hello`。 65 | 66 | 再看一个例子。 67 | 68 | ```bash 69 | $ xargs find -name 70 | "*.txt" 71 | ./foo.txt 72 | ./hello.txt 73 | ``` 74 | 75 | 上面示例中,输入`xargs find -name`以后,命令行会等待用户输入所要搜索的文件。用户输入`"*.txt"`,表示搜索当前目录下的所有 TXT 文件,然后按下 Ctrl+d,表示输入结束,这时就相当执行`find -name *.txt`。 76 | 77 | ## -d 参数与分隔符 78 | 79 | 默认情况下,`xargs`将换行符和空格作为分隔符,把标准输入分解成一个个命令行参数。 80 | 81 | ```bash 82 | $ echo "one two three" | xargs mkdir 83 | ``` 84 | 85 | 上面代码中,`mkdir`会新建三个子目录,因为`xargs`将`one two three`分解成三个命令行参数,执行`mkdir one two three`。 86 | 87 | `-d`参数可以更改分隔符。 88 | 89 | ```bash 90 | $ echo -e "a\tb\tc" | xargs -d "\t" echo 91 | a b c 92 | ``` 93 | 94 | 上面的命令指定制表符`\t`作为分隔符,所以`a\tb\tc`就转换成了三个命令行参数。`echo`命令的`-e`参数表示解释转义字符。 95 | 96 | ## -p 参数,-t 参数 97 | 98 | 使用`xargs`命令以后,由于存在转换参数过程,有时需要确认一下到底执行的是什么命令。 99 | 100 | `-p`参数打印出要执行的命令,询问用户是否要执行。 101 | 102 | ```bash 103 | $ echo 'one two three' | xargs -p touch 104 | touch one two three ?... 105 | ``` 106 | 107 | 上面的命令执行以后,会打印出最终要执行的命令,让用户确认。用户按下回车以后,才会真正执行。 108 | 109 | `-t`参数则是打印出最终要执行的命令,然后直接执行,不需要用户确认。 110 | 111 | ```bash 112 | $ echo 'one two three' | xargs -t rm 113 | rm one two three 114 | ``` 115 | 116 | ## -0 参数与 find 命令 117 | 118 | 由于`xargs`默认将空格作为分隔符,所以不太适合处理文件名,因为文件名可能包含空格。 119 | 120 | `find`命令有一个特别的参数`-print0`,指定输出的文件列表以`null`分隔。然后,`xargs`命令的`-0`参数表示用`null`当作分隔符。 121 | 122 | ```bash 123 | $ find /path -type f -print0 | xargs -0 rm 124 | ``` 125 | 126 | 上面命令删除`/path`路径下的所有文件。由于分隔符是`null`,所以处理包含空格的文件名,也不会报错。 127 | 128 | 还有一个原因,使得`xargs`特别适合`find`命令。有些命令(比如`rm`)一旦参数过多会报错“参数列表过长”,而无法执行,改用`xargs`就没有这个问题,因为它对每个参数执行一次命令。 129 | 130 | ```bash 131 | $ find . -name "*.txt" | xargs grep "abc" 132 | ``` 133 | 134 | 上面命令找出所有 TXT 文件以后,对每个文件搜索一次是否包含字符串`abc`。 135 | 136 | ## -L 参数 137 | 138 | 如果标准输入包含多行,`-L`参数指定多少行作为一个命令行参数。 139 | 140 | ```bash 141 | $ xargs find -name 142 | "*.txt" 143 | "*.md" 144 | find: paths must precede expression: `*.md' 145 | ``` 146 | 147 | 上面命令同时将`"*.txt"`和`*.md`两行作为命令行参数,传给`find`命令导致报错。 148 | 149 | 使用`-L`参数,指定每行作为一个命令行参数,就不会报错。 150 | 151 | ```bash 152 | $ xargs -L 1 find -name 153 | "*.txt" 154 | ./foo.txt 155 | ./hello.txt 156 | "*.md" 157 | ./README.md 158 | ``` 159 | 160 | 上面命令指定了每一行(`-L 1`)作为命令行参数,分别运行一次命令(`find -name`)。 161 | 162 | 下面是另一个例子。 163 | 164 | ```bash 165 | $ echo -e "a\nb\nc" | xargs -L 1 echo 166 | a 167 | b 168 | c 169 | ``` 170 | 171 | 上面代码指定每行运行一次`echo`命令,所以`echo`命令执行了三次,输出了三行。 172 | 173 | ## -n 参数 174 | 175 | `-L`参数虽然解决了多行的问题,但是有时用户会在同一行输入多项。 176 | 177 | ```bash 178 | $ xargs find -name 179 | "*.txt" "*.md" 180 | find: paths must precede expression: `*.md' 181 | ``` 182 | 183 | 上面的命令将同一行的两项作为命令行参数,导致报错。 184 | 185 | `-n`参数指定每次将多少项,作为命令行参数。 186 | 187 | ```bash 188 | $ xargs -n 1 find -name 189 | ``` 190 | 191 | 上面命令指定将每一项(`-n 1`)标准输入作为命令行参数,分别执行一次命令(`find -name`)。 192 | 193 | 下面是另一个例子。 194 | 195 | ```bash 196 | $ echo {0..9} | xargs -n 2 echo 197 | 0 1 198 | 2 3 199 | 4 5 200 | 6 7 201 | 8 9 202 | ``` 203 | 204 | 上面命令指定,每两个参数运行一次`echo`命令。所以,10个阿拉伯数字运行了五次`echo`命令,输出了五行。 205 | 206 | ## -I 参数 207 | 208 | 如果`xargs`要将命令行参数传给多个命令,可以使用`-I`参数。 209 | 210 | `-I`指定每一项命令行参数的替代字符串。 211 | 212 | ```bash 213 | $ cat foo.txt 214 | one 215 | two 216 | three 217 | 218 | $ cat foo.txt | xargs -I file sh -c 'echo file; mkdir file' 219 | one 220 | two 221 | three 222 | 223 | $ ls 224 | one two three 225 | ``` 226 | 227 | 上面代码中,`foo.txt`是一个三行的文本文件。我们希望对每一项命令行参数,执行两个命令(`echo`和`mkdir`),使用`-I file`表示`file`是命令行参数的替代字符串。执行命令时,具体的参数会替代掉`echo file; mkdir file`里面的两个`file`。 228 | 229 | ## --max-procs 参数 230 | 231 | `xargs`默认只用一个进程执行命令。如果命令要执行多次,必须等上一次执行完,才能执行下一次。 232 | 233 | `--max-procs`参数指定同时用多少个进程并行执行命令。`--max-procs 2`表示同时最多使用两个进程,`--max-procs 0`表示不限制进程数。 234 | 235 | ```bash 236 | $ docker ps -q | xargs -n 1 --max-procs 0 docker kill 237 | ``` 238 | 239 | 上面命令表示,同时关闭尽可能多的 Docker 容器,这样运行速度会快很多。 240 | 241 | ## 参考链接 242 | 243 | - [xargs is the inverse function of echo](https://dhashe.com/xargs-is-the-inverse-function-of-echo.html) 244 | - [Linux and Unix xargs command tutorial with examples](https://shapeshed.com/unix-xargs/), George Ornbo 245 | - [8 Practical Examples of Linux Xargs Command for Beginners](https://www.howtoforge.com/tutorial/linux-xargs-command/), Himanshu Arora 246 | -------------------------------------------------------------------------------- /docs/cron.md: -------------------------------------------------------------------------------- 1 | # Cron 定时任务 2 | 3 | ## 简介 4 | 5 | Cron 是一个用来执行定时任务的工具,可以在指定的时间自动执行重复性任务。 6 | 7 | 它的核心是 cron 守护进程,名为 crond。它在后台每分钟运行一次,检查是否有需要在当前时间执行的计划任务。 8 | 9 | 下面命令可以查看 cron 守护进程,是否正常运行。 10 | 11 | ```bash 12 | # Ubuntu / Debian 13 | $ sudo systemctl status cron 14 | # or 15 | $ ps aux | grep cron 16 | 17 | # rockyOS / RHEL 18 | $ sudo systemctl status crond 19 | # or 20 | $ ps aux | grep crond 21 | ``` 22 | 23 | ## crontab 24 | 25 | crond 检查的定时任务,保存在 crontab 文件。该文件的每一行代表一个单独的任务,包含何时运行该任务,以及所要执行的命令。 26 | 27 | crontab 分成两个级别:用户个人的crontab,系统的 crontab。前者由用户本人编辑,后者只能由根用户编辑。 28 | 29 | 系统的 crontab 存放在`/etc/crontab`(或目录`/etc/cron.d/`),以及一系列特殊目录之中:`/etc/cron.daily`、`/etc/cron.hourly`、`/etc/cron.weekly`和`/etc/cron.monthly`。 30 | 31 | `crontab`本身也是一个命令,下面的命令可以检查现有的 cron 任务。 32 | 33 | ```bash 34 | # 当前用户的 cron 任务 35 | $ crontab -l 36 | 37 | # 根用户的 cron 任务 38 | $ sudo crontab -l 39 | 40 | # 某个指定用户的 cron 任务 41 | $ sudo crontab -u [USERNAME] -l 42 | ``` 43 | 44 | ## cron 任务的语法 45 | 46 | crontab 文件的每一行,代表一个 cron 任务。它由多个字段组成,字段之间使用空格或制表符分隔。 47 | 48 | cron 任务的基本语法如下。 49 | 50 | ```bash 51 | minute hour day_of_month month day_of_week command_to_execute 52 | ``` 53 | 54 | 各个字段的含义如下。 55 | 56 | - minute(0-59):指定命令运行的分钟,可以是0到59之间的值,0表示将在一小时开始时运行命令。 57 | - hour(0-23):指定命令运行的小时,以24小时格式指定,例如将其设置为14将在下午2点运行该命令。 58 | - day_of_month(1-31):指定命令运行的日期。它可以是1到31之间的任意值,具体取决于该月的天数。例如,设置为1将在每个月的第一天运行命令。 59 | - month(1-12):指定命令将在哪个月份执行。它可以是 1(一月)到 12(十二月)之间的值。例如,设置为12将在12月执行该命令。 60 | - day_of_week(0-6):指定命令应在一周中的哪一天运行。它可以是0(星期日)到6(星期六)之间的值。例如,设置为5将在每个星期五运行该命令。 61 | - command_to_execute:指定 cron 任务应执行的操作。 62 | 63 | crontab 还允许使用通配符。 64 | 65 | - 星号 (*):代表“每个”时间单位。例如,小时字段中的“*”表示“每小时”。 66 | - 逗号 (,):用于在同一字段指定多个值。例如,day_of_week 字段中的“1,3,5”表示“周一、周三和周五运行”。注意,逗号前后不能由空格。 67 | - 连字符 (-):指定值的范围。例如,小时字段中的“9-17”表示“上午9点到下午5点之间的每小时”。 68 | - 斜杠 (/):指定增量。例如,分钟字段中的“*/10”表示“每10分钟”。 69 | 70 | crontab 还提供一些快捷字符串。 71 | 72 | - @reboot 在启动时运行一次指定的命令 。 73 | - @year,@annually 两者都在每年 1 月 1 日中午 12:00运行指定的任务 。相当于指定“0 0 1 1 *” 74 | - @monthly 每月1 日中午 12:00运行该作业 一次。相当于“0 0 1 * *” 75 | - @weekly 在每周周日中午 12:00运行该作业 一次。相当于“0 0 * * 0” 76 | - @daily,@midnight:两者都在每天中午 12:00运行 cronjob 。这相当于在 crontab 文件中指定“0 0 * * *”。 77 | - @hourly:每小时整点运行该作业 。相当于“0 * * * *” 78 | 79 | crontab 文件中,以“#”符号开头的行表示注释。 80 | 81 | 以下是一些示例。 82 | 83 | - `* * * * *` 每分钟运行一次 cron 任务。 84 | - `0 * * * *` 每小时运行一次 cron 任务。 85 | - `0 0 * * *` 每天午夜运行 cron 任务。 86 | - `0 2 * * *` 每天凌晨 2 点运行 cron 任务。 87 | - `0 0 15 * *` 每个月 15 日午夜运行一次 cron 任务。 88 | - `0 0 0 12 *` 周六午夜运行 cron 任务。 89 | - `0 0 * * 6` 从周一到周五每天下午 3 点运行 cron 任务。 90 | - `0 15 * * 1-5` 从周一到周五每天下午 3 点运行 cron 任务。 91 | - `*/5 * * * *` 每 5 分钟运行一次 cron 任务。 92 | - `0 8-16 * * *` 每天、每小时、从上午 8 点到下午 4 点准时执行 cron 任务。 93 | - `0 4 * * 2,4` 在周二和周四凌晨 4 点运行 cron 作业。 94 | - `@reboot` 系统启动时或 crond 进程启动时运行 cron 任务。 95 | 96 | 此外,还有几个特殊字母。 97 | 98 | `L` 表示 Last,仅适用于“月份中的某一天”和“星期几”。 99 | 100 | ```bash 101 | 0 4 L * * command -每月最后一天凌晨 4 点 102 | 0 4 * * 5L command -每月最后一个星期五凌晨 4 点 103 | ``` 104 | `W`表示 weekday,即该月内最近的一个工作日,仅适用于“月份中的某一天”。 105 | 106 | ```bash 107 | 0 4 15W * * command -每月 15 日最近的工作日(周一至周五)凌晨 4 点 108 | ``` 109 | 110 | `#`表示该月的第几个,仅适用于“星期几”。 111 | 112 | ```bash 113 | 0 4 * * 5#2 -每月第二个周五凌晨 4 点 114 | ``` 115 | 116 | ### 环境变量 117 | 118 | cron 任务在非交互式、非登录 Shell 环境中运行,这意味着它们可能无法访问与手动运行命令时相同的环境变量。 119 | 120 | 这就是说,cron 任务不会自动继承用户或系统的环境变量或路径。这可能会导致 cron 作业失败,无法找到可执行文件或脚本。解决方法是在 crontab 文件中显式设置 PATH 环境变量。 121 | 122 | ```bash 123 | PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin 124 | ``` 125 | 126 | 不过,为了便于调试,建议始终在 cron 任务中使用绝对路径。 127 | 128 | 除了`PATH`环境变量,还可以设置`SHELL`环境变量,指定 cron 使用的 Shell。 129 | 130 | ```bash 131 | SHELL=/bin/sh 132 | ``` 133 | 134 | 上面示例设定执行 cron 任务时,使用 Bash。 135 | 136 | 添加其他环境变量,都是这种格式。 137 | 138 | ```bash 139 | result="HELLO WORLD" 140 | ``` 141 | 142 | 上面示例添加了环境变量`result`,值为“HELLO WORLD”。 143 | 144 | ## cron 任务管理 145 | 146 | ### 个人任务 147 | 148 | 创建或编辑用户的 crontab 文件,使用下面的命令。 149 | 150 | ```bash 151 | # 编辑当前用户的 cron 任务 152 | $ crontab -e 153 | 154 | # 编辑根用户的 cron 任务 155 | $ sudo crontab -e 156 | 157 | # 编辑指定用户的 cron 任务 158 | $ sudo crontab -u [USERNAME] -e 159 | ``` 160 | 161 | 上面的命令会打开系统默认文本编辑器,对用户的 crontab 文件进行编辑。 162 | 163 | 另一种方法是手动把 cron 任务添加到系统的`/etc/cronjob`文件,或者在`/etc/cron.d/`目录中创建一个新文件。建议使用后者,因为`/etc/cronjob`有可能在系统更新时被覆盖。 164 | 165 | 更新上面两个位置的 crontab 文件时,每个任务需要在第六个字段添加某个用户名,表示该任务运行在哪个用户名下。 166 | 167 | ```bash 168 | * * * * * user command 169 | ``` 170 | 171 | 定期运行脚本还有一种方法,就是使用`/etc/cron.*`目录,将脚本保存在以下目录之一的里面,就可以直接以根用户的身份运行该任务。(为了确保脚本可以运行,最好打开脚本的运行权限。) 172 | 173 | - /etc/cron.hourly/ 174 | - /etc/cron.daily/ 175 | - /etc/cron.weekly/ 176 | - /etc/cron.monthly/ 177 | 178 | 添加 cron 任务,只需在 crontab 文件中添加一个新行即可。例如,备份脚本 backup.sh 每天凌晨 3:00 运行,就是添加下面的内容。 179 | 180 | ```bash 181 | 0 3 * * * /home/linuxiac/backup.sh 182 | ``` 183 | 184 | 编辑完成后,保存并退出编辑器。cron 服务会自动检查 crontab 文件,因此无需在更改后重新启动 cron 进程。 185 | 186 | `crontab -e`还会在保存和退出文件时,自动检查语法,防止意外输入无效的 cron 任务。 187 | 188 | 删除某个 cron 任务时,只要删除那一行即可。 189 | 190 | 如果想要删除所有的 cron 任务,只要删除 crontab 文件即可,也可以使用命令行参数`-r`。 191 | 192 | ```bash 193 | # 删除当前用户的所有 cron 任务,而且没有提示 194 | $ crontab -r 195 | ``` 196 | 197 | 上面的命令会删除当前用户的 crontab 文件(即删除所有 cron 任务),而且不会出现任何确认提示,因此请小心使用。 198 | 199 | 如果希望删除前出现确认提示,则可以使用命令行参数`-i`。 200 | 201 | ```bash 202 | # 删除当前用户的所有 cron 任务之前,会有确认提示 203 | $ crontab -i -r 204 | ``` 205 | 206 | 下面是删除根用户和其他用户的 cron 任务。 207 | 208 | ```bash 209 | # 删除根用户的所有 cron 任务 210 | $ sudo crontab -r 211 | 212 | # 删除特定用户的所有 cron 任务 213 | $ sudo crontab -u USERNAME -r 214 | ``` 215 | 216 | ### 系统任务 217 | 218 | 创建系统级别的 cron 任务,需要直接编辑`/etc/crontab`文件。 219 | 220 | ```bash 221 | 0 2 * * * root /usr/bin/find /var/log/myservice -type f -name '*.log' -delete 222 | ``` 223 | 224 | 上面示例设定在每天凌晨2:00,从`/var/log/myservice`目录删除所有带有扩展名为`.log`的文件。 225 | 226 | 它的格式与用户级别的 cron 文件有一个区别,就是在最初表示时间的五个字段后面,多了一个字段,表示执行任务的用户帐户,本例为`root`。 227 | 228 | 直接编辑`/etc/crontab`文件有两个缺点。(1)它不提供语法检查,增加了出错的风险。(2)它会影响整个系统,使用时需要非常谨慎。 229 | 230 | 列出所有的系统级别 cron 任务,需要查看以下所有文件和目录。 231 | 232 | - /etc/crontab 文件 233 | - /etc/cron.d/ 目录 234 | - /etc/cron.daily/ 目录 235 | - /etc/cron.hourly/ 目录 236 | - /etc/cron.weekly/ 目录 237 | - /etc/cron.monthly/ 目录 238 | 239 | ### cron 任务的日志 240 | 241 | cron 任务执行的 stdout 输出不会被记录,必须添加到命令或脚本本身。 242 | 243 | ```bash 244 | 0 4 * * 5L command -v >> /var/logs/command.log 245 | ``` 246 | 247 | 简单的执行记录,可以查看系统日志。Ubuntu / Debian 是`/var/log/syslog`或者`/var/log/auth.log`,RHEL/RHEL 是`/var/log/cron`,可以使用 grep 命令过滤日志。 248 | 249 | ```bash 250 | $ sudo grep -i cron /var/log/syslog /var/log/auth.log 251 | ``` 252 | 253 | ## 参考链接 254 | 255 | - [How to Use Cron on Linux: Tips, Tricks, and Examples](https://linuxiac.com/how-to-use-cron-and-crontab-on-linux/) 256 | - [Cron Jobs on Linux - Comprehensive Guide with Examples](https://ittavern.com/cron-jobs-on-linux-comprehensive-guide/) 257 | 258 | --------------------------------------------------------------------------------