Make参数

-b -m

这两个参数的作用是忽略和其它版本make的兼容性。

-B –always-make

认为所有的目标都需要更新(重编译)。

-C –directory=

指定读取makefile的目录。如果有多个“-C”参数,make的解释是后面的路径以前面的作为相对路径,并以最后的目录作为被指定目录。如:“make –C ~hchen/test –C prog”等价于“make –C ~hchen/test/prog”。

—debug[=]

输出make的调试信息。它有几种不同的级别可供选择,如果没有参数,那就是输出最简单的调试信息。下面是的取值:a —— 也就是all,输出所有的调试信息。(会非常的多)b —— 也就是basic,只输出简单的调试信息。即输出不需要重编译的目标。v —— 也就是verbose,在b选项的级别之上。输出的信息包括哪个makefile被解析,不需要被重编译的依赖文件(或是依赖目标)等。i —— 也就是implicit,输出所以的隐含规则。j —— 也就是jobs,输出执行规则中命令的详细信息,如命令的PID、返回码等。m —— 也就是makefile,输出make读取makefile,更新makefile,执行makefile的信息。

-d相当于 –debug=a

-e –environment-overrides

指明环境变量的值覆盖makefile中定义的变量的值。

-f= –file= –makefile=

指定需要执行的makefile。

-h –help

显示帮助信息。

-i –ignore-errors

在执行时忽略所有的错误。

-I –include-dir=

指定一个被包含makefile的搜索目标。可以使用多个“-I”参数来指定多个目录。

-j [] –jobs[=]

指同时运行命令的个数。如果没有这个参数,make运行命令时能运行多少就运行多少。如果有一个以上的“-j”参数,那么仅最后一个“-j”才是有效的。(注意这个参数在MS-DOS中是无用的)

-k –keep-going

出错也不停止运行。如果生成一个目标失败了,那么依赖于其上的目标就不会被执行了。

-l –load-average[=“—max-load[=]

指定make运行命令的负载。

-n –just-print –dry-run –recon

仅输出执行过程中的命令序列,但并不执行。

-o –old-file= –assume-old=

不重新生成的指定的,即使这个目标的依赖文件新于它。

-p –print-data-base 输出makefile中的所有数据,包括所有的规则和变量。这个参数会让一个简单的makefile都会输出一堆信息。如果你只是想输出信息而不想执行makefile,你可以使用“make -qp”命令。如果你想查看执行makefile前的预设变量和规则,你可以使用“make –p –f /dev/null”。这个参数输出的信息会包含着你的makefile文件的文件名和行号,所以,用这个参数来调试你的makefile会是很有用的,特别是当你的环境变量很复杂的时候。

-q –question

不运行命令,也不输出。仅仅是检查所指定的目标是否需要更新。如果是0则说明要更新,如果是2则说明有错误发生。

-r –no-builtin-rules

禁止make使用任何隐含规则。

-R –no-builtin-variabes

禁止make使用任何作用于变量上的隐含规则。

-s –silent –quiet

在命令运行时不输出命令的输出。

-S –no-keep-going –stop

取消“-k”选项的作用。因为有些时候,make的选项是从环境变量“MAKEFLAGS”中继承下来的。所以你可以在命令行中使用这个参数来让环境变量中的“-k”选项失效。

-t –touch

相当于UNIX的touch命令,只是把目标的修改日期变成最新的,也就是阻止生成目标的命令运行。

-v –version

输出make程序的版本、版权等关于make的信息。

-w –print-directory

输出运行makefile之前和之后的信息。这个参数对于跟踪嵌套式调用make时很有用。

–no-print-directory

禁止 -w 选项。

-W –what-if= –new-file= –assume-file=

假定目标需要更新,如果和“-n”选项使用,那么这个参数会输出该目标更新时的运行动作。如果没有“-n”那么就像运行UNIX的“touch”命令一样,使得的修改时间为当前时间。

–warn-undefined-variables

只要make发现有未定义的变量,那么就输出警告信息。

参考文献

Makefile实例:批量编译多个目标

gist: https://gist.github.com/songtianlun/8984626fd80cd20b7c2e71f95caaf8d1

# Batch Single C file MakeFile

# 指定CPU架构 Architecture -> ARCH
ARCH ?= 
CC = $(ARCH)gcc
SUFFIX = .c
CFLAGS += -Wall -g
LD = 

CUR_SOURCE = $(wildcard *$(SUFFIX))
CUR_TARGETS = $(patsubst %$(SUFFIX), %, $(CUR_SOURCE))

all:$(CUR_TARGETS)

# %:%.c 是一个表示与目标相同 文件的模式变量 
$(CUR_TARGETS):%:%$(SUFFIX)
    $(CC) $< $(CFLAGS) -o $@ $(LD)

# 指定伪目标
.PHONY:clean all
    clean:
        -rm -rf $(TARGETS)

参考文献

Makefile中部分函数的使用

foreach

一、作用

循环处理文件列表。

二、格式

$(foreach var text commond)

var:局部变量

text:文件列表,空格隔开,每一次取一个值赋值为变量var

commond:对var变量进行操作(一般会使用var变量,不然没意义),每次操作结果都会以空格隔开,最后返回空格隔开的列表。

wildcard

功能是展开成一列所有符合由其参数描述的文 件名,文件间以空格间隔。你可以像下面所示使用这个命令:

SOURCES= $(wildcard *.c)

这行会产生一个所有以 .c 结尾的文件的列表,然后存入变量 SOURCES 里。当然你不需要一定要把结果存入一个变量。

notdir

把展开的文件的路径去掉,只显示文件名而不包含其路径信息,例如:

FILES =$(notdir $(SOURCES))

这行的作用是把上面以 .c 结尾的文件的文件列表中附带的路径去掉,只显示符合条件的文件名。

patsubst

( patten substitude, 匹配替换的缩写)函数。它需要3个参数:第一个是一个需要匹配的式样,第二个表示用什么来替换它,第三个是一个需要被处理的由空格分隔的字列。例如,处理那个经过上面定义后的变量,

OBJS = $(patsubst %.c,%.o,$(SOURCES))

这行将处理所有在 SOURCES 列个中的字(一列文件名),如果它的 结尾是 .c ,就用 .o.c 取代。注意这里的 % 符号将匹配一个或多个字符,而它每次所匹配的字串叫做一个‘柄’(stem) 。在第二个参数里, % 被解读成用第一参数所匹配的那个柄。

参考文献

Makefile基础语法

Makefile 是描述文件依赖关系的说明,由若干个规则组成,每个 规则 的格式如下:

目标:依赖关系
<tab键> 命令

其中:

  • 目标 是指 make 最终要创造的产物,也是 make 执行的动作名称,例如 clean
  • 依赖关系 是指编译目标体需要依赖的一个或多个文件列表;
  • 命令 是指为了从依赖文件创造目标文件所需执行的命令。

make 执行的动作也是一个目标,为避免该目标和文件目标冲突,可以使用以下格式将动作指定伪目标:

.PHONY: clean
clean:
        rm *.o temp

在使用时,在具有 Makefile 文件的项目目录下通过如下命令运行:

$ make [target]

其中的参数 target 是指要处理的目标名,不指定则默认为 make all 。除了 Makefile ,还可将文件命名为 GNUmakefile, makefile ,命令执行时按照 GNUmakefileMakefilemakefile 的顺序搜索 Makefile 文件。

预定义变量

为使命令编写更快捷,免去无意义的重复操作,有一些预定义变量可以用于简化 Makefile

$@    # 规则目标对应的文件名
$*    # 不包含扩展名的目标文件名称
$+    # 所有的依赖文件,用空格分开,可能包含重复
$%    # 如果目标是归档成员,则该变量标识目标的归档成员名称
$<    # 规则中第一个依赖文件名
$^    # 规则中所有依赖的列表,空格分隔
$?    # 规则中日期新于目标的所有依赖文件的列表,空格分隔
$(@D) # 目标文件的目录部分
$(@F) # 目标文件的文件名部分

Make/Makefile 简介

Make 工具可用于在 Unix-likeMicrosoft Windows 系统上,根据 Makrfile 文件指定的目标及步骤,自动编译构建、更新目标文件。

  • 类Unix

Makefile起源于类Unix系统,在此类环境中仍然是主要的软件构建机制。

  • Microsoft Windows

Windows通过其nmake实用程序支持各种makefile文件。可以在Windows的Cygwin环境或Mingw中执行类似Unix的标准makefile 。

参考文献

自建KMS服务器 | 持续激活Windows

最近在 GitHub 上发现一个项目:

该项目中提供了一个可以一键安装KMS服务器的脚本,可以在 Linux / Windows 设备上一键安装 KMS 服务器,未来就可以通过自建的KMS服务器激活Windows服务了,使用方法也很简单。

  • 支持 Windows Vista/7/8/8.1/10 LTSB/LTSC系列 神州网信系列 Windows server 2008/2008R2/2012/2012R2/2016/2019
  • 支持 Office 2010/2013/2016/2019 Office 365

这里简单介绍激活Windows的方法,详细教程请移步官方 教程

Linux 系统下安装方法

# 一键安装KMS服务 (Debian/Ubuntu/Mint 等)
$ wget -N --no-check-certificate git.io/k.sh && chmod +x k.sh && bash k.sh debian

# 一键安装KMS服务 (CentOS/Redhat/Fedora 等)(如果系统开启了防火墙 须自行开放 1688 端口)
$ wget -N --no-check-certificate git.io/k.sh && chmod +x k.sh && bash k.sh centos

# 启动KMS服务
$ bash k.sh start

# 服务器IP地址既是KMS服务器地址
# 也可以将域名解析至IP使用(支持IPv6 即AAAA记录)

# 关闭KMS服务
$ bash k.sh stop

# 添加开机自启动KMS服务
$ bash k.sh auto

# 重启KMS服务
$ bash k.sh restart

# 查看KMS服务运行状态
$ bash k.sh status

# 卸载KMS服务
$ bash k.sh uninstall

# 更多详细教程:https://v0v.bid/kms.html

[kms.sh](http://kms.sh) 脚本备份:

#!/bin/bash

#====================================================
#   System Request: Debian/Ubuntu/Mint/CentOS/Redhat/Fedora
#   Author: dylanbai8
#   Dscription: KMS服务一键安装脚本
#   Open Source: https://github.com/dylanbai8/kmspro
#   Official document: https://v0v.bid
#====================================================

# 定义脚本变量
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
STAT=2

# Debian系列操作系统安装KMS
do_debian(){
apt-get install gcc git make -y
rm -rf /usr/local/kms
mkdir /usr/local/kms
cd /usr/local/kms
git clone https://github.com/Wind4/vlmcsd.git
cd vlmcsd
make
cd bin
mv vlmcsd /usr/local/kms/kms
cd /usr/local/kms/
rm -rf ./vlmcsd/
mv kms vlmcsd
echo "KMS服务安装成功!"
echo "更多教程请访问:https://v0v.bid/kms.html"
}

# Centos系列操作系统安装KMS
do_centos(){
yum install gcc git make -y
rm -rf /usr/local/kms
mkdir /usr/local/kms
cd /usr/local/kms
git clone https://github.com/Wind4/vlmcsd.git
cd vlmcsd
make
cd bin
mv vlmcsd /usr/local/kms/kms
cd /usr/local/kms/
rm -rf ./vlmcsd/
mv kms vlmcsd
echo "KMS服务安装成功!"
echo "更多教程请访问:https://v0v.bid/kms.html"
echo "Centos请自行开放1688端口"
}

# 检测KMS运行状态
check_running(){
PID=`ps -ef | grep -v grep | grep -i "vlmcsd" | awk '{print $2}'`
        if [ ! -z $PID ]; then
        STAT=0
    else
        STAT=1
    fi
}

# 重启KMS服务
do_restart(){
    check_running
    if [ $STAT = 0 ]; then
        echo "KMS服务已经运行 正在重新启动 ..."
        kill $PID
    elif [ $STAT = 1 ]; then
        echo "KMS服务未运行 正在启动 ..."
    fi
    /usr/local/kms/vlmcsd
    check_running
    if [ $STAT = 0 ]; then
        local_ip=`curl -4 ip.sb`
        echo "KMS服务 启动成功"
        echo "[Windows一句命令激活] 命令提示符(管理员):slmgr /skms ${local_ip} && slmgr /ato"
        echo "更多教程请访问:https://v0v.bid/kms.html"
    elif [ $STAT = 1 ]; then
        echo "KMS服务 启动失败"
    fi
}

# 停止KMS服务
do_stop(){
    check_running
    if [ $STAT = 0 ]; then
            echo "正在停止 KMS服务 ..."
        kill $PID
        check_running
        if [ $STAT = 0 ]; then
            echo "停止 KMS服务 失败"
        elif [ $STAT = 1 ]; then
            echo "停止 KMS服务 成功"
            fi
        elif [ $STAT = 1 ]; then
                echo "KMS服务 未运行 取消操作"
        fi
}

# 检测KMS服务是否运行
do_status(){
    check_running
    if [ $STAT = 0 ]; then
                echo "KMS服务 正在运行"
                echo "更多教程请访问:https://v0v.bid/kms.html"
        elif [ $STAT = 1 ]; then
                echo "KMS服务 未运行"
        fi
}

# 启动KMS服务
do_start(){
    check_running
    if [ $STAT = 0 ]; then
                echo "KMS服务 已运行 取消操作"
                echo "更多教程请访问:https://v0v.bid/kms.html"
        exit 0;
        elif [ $STAT = 1 ]; then
                echo "正在启动 KMS服务 ..."
    /usr/local/kms/vlmcsd
    fi
        check_running
        if [ $STAT = 0 ]; then
                local_ip=`curl -4 ip.sb`
                echo "KMS服务 启动成功"
                echo "[Windows一句命令激活] 命令提示符(管理员):slmgr /skms ${local_ip} && slmgr /ato"
                echo "更多教程请访问:https://v0v.bid/kms.html"
        elif [ $STAT = 1 ]; then
                echo "KMS服务 启动失败"
        fi
}

# 添加开机自启动服务
do_auto(){
    echo "/usr/local/kms/vlmcsd" >> /etc/rc.local
    chmod +x /etc/rc.local
    echo "已添加 开机自启动 KMS服务"
    echo "更多教程请访问:https://v0v.bid/kms.html"
}

# 卸载KMS服务
do_uninstall(){
    do_stop
    rm -rf /usr/local/kms
    sed -i '/vlmcsd/'d /etc/rc.local
    echo "KMS服务 已卸载"
}

# 脚本菜单
case "$1" in
    debian|centos|start|stop|auto|restart|status|uninstall)
    do_$1
    ;;
    *)
    echo "缺少参数: debian | centos | start | stop | auto | restart | status | uninstall "
    echo "更多教程请访问:https://github.com/dylanbai8/kmspro"
    ;;
esac

# 转载请保留版权:https://v0v.bid

Windows 下的安装方法请自行前往仓库查看,安装好服务后直接通过一行指令即可激活Windows,例如本站的KMS服务器地址为:kms.frytea.com,您只需要在Windows命令提示符中运行以下命令:

$ slmgr /skms kms.frytea.com && slmgr /ato

即可成功激活。

参考文献

Chevereto 配合 Picgo 打造个人相册/图床解决方案

Chevereto 是一款很好用图床工具,可以实现一键上传、一键 Markdown 引用等功能,最近发现还可以和 Picgo 配合起来使用,打造更加方便实用个人图床。

Picgo 是一个用于快速上传图片并获取图片 URL 链接的工具,支持全桌面客户端,应该是目前本人用过最好用的图床链接工具了。

今天主要介绍如何使用Chevereto + Picgo 实现一键上传图片到特定用户、相册中


至于 Chevereto 的安装和 Picgo 的安装,网上教程很多,不再赘述,在这里给出一些参考链接,自取:


在Picgo上实现api上传的工具很多,如 cheveretoweb-uploader 等。

https://imagehost-cdn.frytea.com/images/2020/10/05/202010050845595bff58306dff0429.png

但Chevereto默认的api会将图片上传到访客目录下,不支持自定义。因此在这里通过修改源代码的方式实现上传图片到特定用户的特定目录下。

Chevereto 安装目录下找到这个文件:

app/routes/overrides/route.api.php

注:若不存在,请从上一级目录中拷贝一个 route.api.php 至该目录下。

按照如下方式修改该文件:

- $uploaded_id = CHV\Image::uploadToWebsite($source);
+ // $uploaded_id = CHV\Image::uploadToWebsite($source); 
+ $uploaded_id = CHV\Image::uploadToWebsite($source, 'testuser', array('album_id'=>3));

其中, testuser 和后面的相册 id ,为最终 api 上传图片所在用户的相册下,您可以根据自己的需求设定。之后重载 PHP 即可。

参考文献

夺冠的感觉? | 精神传承 | 自我到为人

今天组织集体去看了电影《夺冠》。

《夺冠》是由中宣部与国家体育总局联合拍摄,由陈可辛执导的剧情运动片,巩俐、黄渤、吴刚、彭昱畅、白浪、中国女子排球队领衔主演。该片于2020年9月25日在中国内地上映。

整场电影,最令我泪目的是郎平的教练在大年三十将队员父母请来共度除夕的那一刻,以及中国队两次打破非冠时期的夺冠时刻。

https://imagehost-cdn.frytea.com/images/2020/09/30/2020093000323863881fae32f07e94.png

全篇看完令我印象最深的是郎平的那句:

  • 你为什么打排球?

还有那句:

  • 一代不如一代

今天就想写下这篇文字,记下这几个关键词,还有我自己的思考。每一代人都有自身的担子,上一代人肩负祖国振兴的重担,而我们这一代人的担子,又是什么呢?

壹 · 为什么而奋斗

人们常说,要为伟大的事业奋斗终身。上一辈人,为祖国的繁荣复兴,奋斗了一生,中国人站起来了。

但是到我们这一代,许多人生来,就已经对许多先进的事务习以为常。而越是向上发展的事物,越是虚无缥缈。

https://imagehost-cdn.frytea.com/images/2020/09/30/20200930003254ee0ad7695acd9c69.png

这些产物,远不如“两弹一星”那么伟大,远不如杂交水稻的成功这么看得见摸得着,反之可能是看不见摸不着的。假如有这么一个人,在原本就富足的企业里,促进了大家的团结、改善了工作效率、使得一切事情变得顺利了这么一点点。或许明察秋毫的好领导会一眼注意到,但是许多人可能都注意不到这些小细节。只有在特定的时期可以去注意到。

软实力,将会成为未来的主旋律。

贰 · 掌万物却空心

现在的人们,物质生活极大丰富,反而没了精神。

上个世纪的人们,什么都缺,他们那时候缺的东西,在现在这个时代都成为了富足的部分。但在那个时代,人们一心想要去追赶,过上更好的生活,于是这股精神,成了他们的骄傲。

在这个时代,也许大多数人已经过上了在上个世纪属于天上人间的生活。但就在这样较好的环境之中,反而迷失了方向,时常感觉到空虚。

https://imagehost-cdn.frytea.com/images/2020/09/30/2020093000331756bb3b93efe6d8e0.png

有人说这个时代,就是贩卖焦虑的时代。

从某种意义上讲,的确如此。越是不知道做什么,就越是焦虑,越是焦虑,就越是感觉不到人生的意义。因此说有一些人,掌万物却空着心。

我想这是许多人需要去静下心来思考的问题,自己究竟想要干什么。每个人的答案都不一样。

叁 · 未来的重担

当代人们的担子是什么样子的呢?

电影中除了女排精神,还传达出一个重要的信息:现代信息技术决定未来。

郎平年轻的时代,通过刻苦努力,赢过使用计算机分析战术的美国队。后来郎平当教练了,通过计算机技术分析战局,打败了当时的世界第一巴西队。

也许这就是未来。竞争的不再是看得见摸得着的硬本领,而是看不见摸不着的软实力。未来的竞争,归根到底是核心科技的竞争。

https://imagehost-cdn.frytea.com/images/2020/09/30/202009300033549064faf5e12a7b17.png

有些事情,中国人并不是做不成,而是没有去做。

就像最近被十几亿中国人挂念的中国芯。中国人并不是做不出来,而是真的没有去下定决心去做。操作系统也是这样,中国人并不是没有做,而是没有这样一个转折点,鞭策着中国人下定决心干出来。

从技术的角度分析,操作系统、芯片,这些都不是一朝一夕的本领,是需要长期、大量人才和经费的投入,才有可能出成果的方向。

无论到何时,都要相信:静下心来研究底层原理,准没错。

总结

这个世界的运行机制很简单很简答,正是因为它很简单,才能够不断的发展壮大。许多看似高不可攀、错综复杂的系统,都是由一个个很简单的小逻辑构成的。

这个时代,不再缺少物质环境,缺少的,是能够静下心来做事情的这颗心。

走出电影院,感慨万千。

微PE制作U盘启动盘,并安装Win10

微PE 是一款很好用的 WinPE (Windows预先安装环境(英语:Microsoft Windows Preinstallation Environment),简称Windows PE或WinPE)工具箱,可以用来制作一个随插随用的U盘启动盘,并且不影响U盘的日常使用,在 Windows 系统电脑的系统出问题时会是救命般的存在。下面就来介绍一下如何制作 PE启动盘 ,并使用它来安装 Win10 操作系统。

制作之前,您需要准备:

  • 16GB以上的U盘(至少要能够装下您准备安装的操作系统镜像)
  • 系统镜像(推荐官方渠道或是MSDN下载)

U盘启动盘制作

第一步,下载微PE工具箱

官网下载即可:http://www.wepe.com.cn/download.html

第二步,制作U盘启动盘

插入U盘,启动微PE软件,选择安装进U盘。

https://imagehost-cdn.frytea.com/images/2020/09/28/2020092821465758c6205482d998f2.png

之后选择您插入的U盘,其他的默认即可。

至此,您的U盘启动盘已制作完毕,有了它,您就可以脱离硬盘引导系统启动,并在这个环境中安装Windows系统啦。

安装Win10

第一步,进入微PE

将您在上一步制作好的U盘启动盘插入待安装系统的电脑,之后选择U盘启动,使用U盘引导启动(至于如何选择U盘启动,不同型号的计算机方法也不同,请自行根据自己的电脑品牌及型号查找)

成功进入后,您就可以进入这样一个酷似Win10的界面:

https://imagehost-cdn.frytea.com/images/2020/09/28/20200928215214b105da316242752e.png

第二步,安装Win10

如果您需要安装Win10,选择桌面上的Windows安装器。

选择您的镜像文件,选择需要安装的驱动器,也可勾选无值守安装,之后一步步安装即可。

https://imagehost-cdn.frytea.com/images/2020/09/28/20200928215455b5d146fae62c722b.png

第三步,激活

您可以使用本站提供的 KMS 服务器激活您的windows系统,只需要以管理员权限在命令提示符运行如下命令:

slmgr /skms kms.frytea.com && slmgr /ato

即可完成激活。

Linux 特殊权限 SUID,SGID,SBIT

setuid 和 setgid 分别是 set uid ID upon execution 和 set group ID upon execution 的缩写。我们一般会再次把它们缩写为 suid 和 sgid。它们是控制文件访问的权限标志(flag),它们分别允许用户以可执行文件的 owner 或 owner group 的权限运行可执行文件。

SUID

当 s 出现在文件拥有者的 x 权限上时,就被称为 SETUID BITS 或 SETUID 。

$ ls -ld /usr/bin/passwd 
-rwsr-xr-x 1 root root 68208 May 28 06:37 /usr/bin/passwd

其特点如下:

  • SUID 权限仅对二进制可执行文件有效
  • 如果执行者对于该二进制可执行文件具有 x 的权限,执行者将具有该文件的所有者的权限
  • 本权限仅在执行该二进制可执行文件的过程中有效

SGID

当 s 标志出现在用户组的 x 权限时称为 SGID。SGID 的特点与 SUID 相同

当一个目录设置了 SGID 权限后,它具有如下功能:

  1. 用户若对此目录具有 r 和 x 权限,该用户能够进入该目录
  2. 用户在此目录下的有效用户组将变成该目录的用户组
  3. 若用户在此目录下拥有 w 权限,则用户所创建的新文件的用户组与该目录的用户组相同

SBIT

其实 SBIT 与 SUID 和 SGID 的关系并不大。SBIT 是 the restricted deletion flag or sticky bit 的简称。SBIT 目前只对目录有效,用来阻止非文件的所有者删除文件。

权限信息中最后一位 t 表明该目录被设置了 SBIT 权限。SBIT 对目录的作用是:当用户在该目录下创建新文件或目录时,仅有自己和 root 才有权力删除。

$ ls -ld /tmp
drwxrwxrwt 12 root root 4096 Sep 16 01:50 /tmp

设置 SUID、SGID、SBIT 权限

$ chmod u+s testfile # 为 testfile 文件加上 SUID 权限。
$ chmod g+s testdir  # 为 testdir 目录加上 SGID 权限。
$ chmod o+t testdir  # 为 testdir 目录加上 SBIT 权限。

参考文献