前言
在维护 Jenkins Slave Node(这里指 macOS 构建机)的过程,不可避免地是你会遇到一些文件访问权限和进程常驻的问题。所以,如果要解决这些问题,就要求你了解 Linux 文件访问权(包括文件和目录,以下统称文件)和什么是守护进程(macOS launchd)。
那么,回到今天本文,也将会从常用 Linux 文件访问权相关命令开始,一步一步带你了解这些其中的所以然。
一、Linux 文件访问权相关命令
首先,我们需要建立的基础认知是在 Linux 系统中,文件的访问者身份划分这 3 类:
- 文件属主,某个用户,例如
root
- 文件所属组,某个用户组,例如
staff
、wheel
- 其他用户,不是上面 2 者
下面,我们再来分别认识下在查看和修改文件访问权过程会使用到的命令。
1.1 ls -l, ls -la
ls
这个命令,我想应该很多同学都知道,可以用于查看某个目录下有哪些文件,例如:
wujingchang@wujingchangdeMacBook-Pro ant-design % ls
AUTHORS.txt README-zh_CN.md package-lock.json
CHANGELOG.en-US.md README.md package.json
CHANGELOG.zh-CN.md SECURITY.md renovate.json
CNAME components scripts
CODE_OF_CONDUCT.md docs site
LICENSE index-style-only.js tests
README-ja_JP.md index-with-locales.js tsconfig.json
README-pt_BR.md index.js tsconfig.node.json
README-sp_MX.md jest-puppeteer.config.js typings
README-uk_UA.md node_modules webpack.config.js
而 ls
的 -l
Option 可以用于查看文件属主、所属组、读写权限和文件大小等信息:
wujingchang@wujingchangdeMacBook-Pro ant-design % ls -l
-rw-r--r-- 1 wujingchang staff 50839 11 9 12:50 AUTHORS.txt
-rw-r--r-- 1 wujingchang staff 320126 11 9 12:50 CHANGELOG.en-US.md
-rw-r--r-- 1 wujingchang staff 334949 11 9 12:50 CHANGELOG.zh-CN.md
-rw-r--r-- 1 wujingchang staff 16 11 9 12:50 CNAME
-rw-r--r-- 1 wujingchang staff 3254 11 9 11:39 CODE_OF_CONDUCT.md
-rw-r--r-- 1 wujingchang staff 1099 11 9 11:39 LICENSE
-rw-r--r-- 1 wujingchang staff 10155 11 9 12:50 README-ja_JP.md
-rw-r--r-- 1 wujingchang staff 9903 11 9 11:39 README-pt_BR.md
-rw-r--r-- 1 wujingchang staff 9801 11 9 12:50 README-sp_MX.md
-rw-r--r-- 1 wujingchang staff 10623 11 9 11:39 README-uk_UA.md
-rw-r--r-- 1 wujingchang staff 9596 11 9 11:39 README-zh_CN.md
# 省略若干目录
其中,如果当你还想隐藏文件的信息的时候则可以使用 ls -la
。那么,可以看到这里主要 9 列,分别表示的含义为:读写权限信息、链接目录数和文件路径长度(例如 /demo/test
此时为 2)、属主、所属组、文件大小、创建月份、创建日、创建时间、文件名称,例如 AUTHORS.txt
:
# 读写权限 链接目录数和文件路径长度 属主 所属组 文件大小 创建月 日 时间 文件名
-rw-r--r-- 1 wujingchang staff 50839 11 9 12:50 AUTHORS.txt
很显然,我们关注的是第一列(文件读写权限信息),而它则是由长度为 10 的字符组成:
- 第 1 位 表示文件还是目录,例如文件是
-
、目录是d
和链接目录是l
等 - 第 2~4 位表示属主的权限,其中
r
表示读(Read)权限,w
表示写(Write)权限,x
表示执行(execute
)权限,-
则表示无权限 - 第 5~7 位表示所属组的权限
- 第 8 ~ 10 位表示其他用户的权限
例如,这里 AUTHORS.txt
的读写权限信息 -rw-r--r--
则表示:
-
普通文件rw-
可读、可写、不可执行(因为是一个普通文件不是可执行程序)r--
可读、不可写、不可执行,也就是说同样是staff
组的用户(除开wujingchang
)只能读这个文件不能写r--
同上
1.2 chmod
chmod">chmod
是 change mode 的缩写,表示改变文件的权限。我们可以通过 chmod
+
和要获取的权限 r
、w
、x
来更改具体的文件权限,例如 chmod +w
表示增加可写的权限,反之 -w
则表示移除可写的权限。
同样是 AUTHORS.txt 文件,我们把原本的可读权限去掉:
wujingchang@wujingchangdeMacBook-Pro ant-design % chmod -r AUTHORS.txt
需要注意的是,-r
默认修改的是属主的访问权限,我们可以通过 u-r
(属主)、g-r
(所属组)、o-r
(其他用户)的方式移除指定的读取权限。
那么,现在 AUTHORS.txt
文件的权限信息则是:
wujingchang@wujingchangdeMacBook-Pro ant-design % ls -l AUTHORS.txt
--w------- 1 wujingchang staff 50839 11 9 12:50 AUTHORS.txt
可以看到原先的 r
都被移除了,此时,如果尝试打开 open AUTHORS.txt
,则会提示:
此外,除了使用字符 r
、w
、x
的方式修改,我们还可以用数字的方式修改(4 可读,2 可写,1 可执行),例如同样是移除 AUTHORS.txt 的读权限:
wujingchang@wujingchangdeMacBook-Pro ant-design % chmod 020 AUTHORS.txt
1.3 chown
chown">chown
是 change ownership 的缩写,表示我们可以更改文件的访问权。例如,我们可以修改 AUTHORS.txt 文件的属主为 root
:
wujingchang@wujingchangdeMacBook-Pro ant-design % sudo chown root AUTHORS.txt
注意由于 root
是超级用户,所以需要 sudo
。然后,此时 AUTHORS.txt 的属主则会变成 root
:
wujingchang@wujingchangdeMacBook-Pro ant-design % ls -l AUTHORS.txt
-rw-r--r-- 1 root staff 50839 11 9 12:50 AUTHORS.txt
那现在我们能使用 open AUTHORS.txt
打开吗?答案是可以,因为 wujingchang
和 root
属于同一个组 staff
,而 -rw-r--r--
的第 4~7 位 r--
表示可读、不可写不可执行,并且其他用户也是 r--
。所以,此时仍然是可以打开 AUTHORS.txt 文件,但是打开后会处于只读的模式:
那么,如果希望在修改文件属主的同时也修改文件所属组,可以在使用 chown
的时候通过 user:group
的方式修改:
wujingchang@wujingchangdeMacBook-Pro ant-design % sudo chown root:wheel AUTHORS.txt
wujingchang@wujingchangdeMacBook-Pro ant-design % ls -ls AUTHORS.txt
104 -rw-r--r-- 1 root wheel 50839 11 9 12:50 AUTHORS.txt
然后,则是其他用户的可读权限,这可以通过 chmod
修改:
wujingchang@wujingchangdeMacBook-Pro ant-design % open AUTHORS.txt
wujingchang@wujingchangdeMacBook-Pro ant-design % sudo chmod o-r AUTHORS.txt
wujingchang@wujingchangdeMacBook-Pro ant-design % ls -ls AUTHORS.txt
104 -rw-r----- 1 daemon wheel 50839 11 9 12:50 AUTHORS.txt
The application cannot be opened for an unexpected reason, error=Error Domain=NSOSStatusErrorDomain Code=-5000 "afpAccessDenied: Insufficient access privileges for operation " UserInfo={_LSLine=3863, LSErrorDict={
Action = odoc;
Documents = (
"AUTHORS.txt"
);
ErrorCode = "-5000";
FullPaths = (
"/Users/wujingchang/Documents/repo/ant-design/AUTHORS.txt"
);
}, _LSFunction=_LSOpenStuffCallLocal}
1.4 chgrp
chgrp">chgrp
是 change group 的缩写,表示我们可以更改文件的所属组的访问权。也就是说,除开使用 chmod
的时候指明用户组的方式修改所属组的访问权,我们还可以通过 chgrp
来直接修改 AUTHORS.txt 文件的所属组:
wujingchang@wujingchangdeMacBook-Pro ant-design % sudo chgrp wheel AUTHORS.txt
二、Launchd
通常,我们在注册连接 Jenkins Slave Node 的时候是希望它常驻在内存中。这在 Windows 机器上,我们可以通过 Services 的方式实现。而在 macOS 上,我们可以通过launchd 提供的守护进程相关的能力实现。
launchd 则是 Apple Inc 创建的一个初始化和操作系统服务管理守护进程。在 Launchd 中有 2 个主要的程序 launchd 和 launchctl,前者用于启动系统和运行服务,后者用于控制服务。
所以,在 macOS 启动过程,会加载 launchd,launchd 则会运行 /etc/rc
,扫描系统 System、用户 User 下、全局的 /Library/LaunchDaemons 和 /Library/LaunchAgents 目录下的脚本,根据需要在 plist 上调用 launchctl,然后 launchd 启动登录窗口。
其中 LaunchDaemons
和 LaunchAgents
处于不同的文件位置所执行的用户有所不同:
类型 | 文件位置 | 运行的用户 |
---|---|---|
User Agents | ~/Library/LaunchAgents | 当前登录用户 |
Global Agents | /Library/LaunchAgents | 当前登录用户 |
Global Daemons | /Library/LaunchDaemons | root 或者指定的用户 |
Global Agents | /System/Library/LaunchAgents | 当前登录用户 |
Aystem Daemons | /System/Library/LaunchDaemons | root 或者指定的用户 |
可以看到,LaunchAgents
是只能以当前的登录用户运行,而 LaunchDaemons
可以指定特定的用户,并且需要注意的是只有 LaunchAgents
可以访问 macOS GUI 的。
如果,我们期望通过 launchd 运行指定的程序(launch Job 或 Service,以下统称 launch Job),则需要在上述的文件目录下配置以 .plist
扩展名的 XML 文件,这通常也被称为 Plist 文件。那么,下面我们来一起看下如何创建一个 launchd Job?
2.1 launchd Job 创建
用于创建 launchd Job 的 Plist 文件配置提供了诸多 Key-Value 来实现指定的声明,这里我们来看 4 个比较常用的 Key:
Label
用于表示 Daemon 的名称,唯一标识ProgramArguments
用于表示 Daemon 启动时需要执行的命令行相关UserName
用于表示启动 Daemon 的用户,例如你可以声明为wujingchang
KeepAlive
用于表示是否 Daemon 需要按需运行还是必须运行
那么,以 Jenkins Slave Node 的连接为例,它需要我们在构建机器(macOS 机器)上通过指定的 Java 命令建立和 Jenkins 服务器的远程连接,这看起来会是这样:
java -jar agent.jar -jnlpUrl http://xxxxxxx/jenkins-agent.jnlp -secret xxxxxxxx -workDir D:\jenkins
所以,它的 lauchd Job 的配置会是:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.jenkins.slavenode</string>
<key>ProgramArguments</key>
<array>
<string>java</string>
<string>-jar</string>
<string>-jnlpUrl</string>
<string>http://xxxxxxx/jenkins-agent.jnlp</string>
<string>-secret</string>
<string>xxxxxxxx</string>
<string>-workDir</string>
<string>D:\jenkins</string>
</array>
<key>UserName</key>
<string>wujingchang</string>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
并且,需要注意的是 launchd Job 的 Plist 文件需要按前面提及的 LaunchDaemons
的文件位置存放(保证开机自启的行为),例如这里的 wujingchang
是当前用户,那么就把 Plist 文件放到 ~/Library/LaunchDaemons
文件目录下。
2.2 launchctl 命令使用
在创建好 launchd Job 的 Plist 文件后,后续在机器开启的过程则会执行对应的 Job。那么,也就是说我们刚创建的 launchd Job 需要等待下次开机才能运行。
所以,如果你新创建的 launchd Job 也需要马上运行,那么则可以使用 launchctl
提供的命令,常用的 launchctl
命令有:
launchctl load
加载启动 launchd Joblaunchctl unload
卸载停止 launchd Joblaunchctl list
查看已启动的访问 lauchd Job 信息
那么,回到上面的例子,我们可以使用 launchctl load
命令运行刚创建的 launch Job:
launchctl load ~/Library/LaunchDaemons/slavenode.plist
此外,我们还可以通过 brew services
相关的命令来启动和停止 launchd Job,具体大家可以通过 brew services --help
了解,这里不做展开。
结语
通过,了解文件访问权修改和 launchd 相关的知识,可以让我们在 Jenkins 排障的维护过程处理访问权限更得心应手,避免由于知识盲区的存在导致问题迟迟不能解决或者解决的成本较高的情况出现。并且,需要注意的是每个修改文件访问权相关的命令(chmod
、chown
、chgrp
)都支持使用 -h
Option 查看相关的介绍,例如 chown -h
:
wujingchang@wujingchangdeMacBook-Pro @ant-desgin % chown -h
usage: chown [-fhnvx] [-R [-H | -L | -P]] owner[:group] file ...
chown [-fhnvx] [-R [-H | -L | -P]] :group file ...
最后,如果文中存在表达不当或错误的地方,欢迎各位同学提 Issue ~
点赞
通过阅读本篇文章,如果有收获的话,可以点个赞,这将会成为我持续分享的动力,感谢~
我是五柳,喜欢创新、捣鼓源码,专注于源码(Vue 3、Vite)、前端工程化、跨端等技术学习和分享,欢迎关注我的微信公众号 Code center 或 GitHub 。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。