saas建站平台wordpress的pingsu主题

web/2025/10/8 6:55:59/文章来源:
saas建站平台,wordpress的pingsu主题,钻磊云主机,wordpress 分页 美化Linux namespaces 介绍 namespaces是Linux内核用来隔离内核资源的方式。通过namespaces可以让一些进程只能看到与自己相关的那部分资源。而其它的进程也只能看到与他们自己相关的资源。这两拨进程根本感知不到对方的存在。而它具体的实现细节是通过Linux namespaces来实现的。 … Linux namespaces 介绍 namespaces是Linux内核用来隔离内核资源的方式。通过namespaces可以让一些进程只能看到与自己相关的那部分资源。而其它的进程也只能看到与他们自己相关的资源。这两拨进程根本感知不到对方的存在。而它具体的实现细节是通过Linux namespaces来实现的。 总结: Linux namespaces对系统进程进行轻量的虚拟化隔离。 当前Linux内核只支持6中namespaces: ● mnt(mount points, filesystems) ● pid(process) ● net(network stack) ● ipc(System V IPC) ● uts(hostname) ● user(UIDs) 下面是Linux Kernel版本迭代过程中对这6中namespaces的支持情况及对应的flag: 最初打算对Linux内核支持10种namespaces,但是下面的4中没有实现: ● security namespace ● security keys namespaces ● device namespace ● time namespace 接下来先介绍namespace的API,然后在针对Linux内核现在支持的6中namespace分别进行介绍。 代码测试环境ubuntu20.04.2kernel版本5.4.0-182-generic Namespaces API 介绍 下面3个系统调用API会被用于namespaces: ● clone(): 用于创建新的进程同时创建新的namespaces。并且新的进程会被attach到新的namespace里面。 int clone(int (*fn)(void *), void *child_stack,int flags, void *arg, .../* pid_t *ptid, void *newtls, pid_t *ctid */ );● 参数child_func传入子进程运行的程序主函数。 ● 参数child_stack传入子进程使用的栈空间 ● 参数flags表示使用哪些CLONE_*标志位 ● 参数args则可用于传入用户参数 ClONE_NEW* flag有20多被包含在include/linux/sched.h头文件中。 ● unshare(): 不会创建新的进程但是会创建新的namesapce并把当前的进程attach到该namespace里面。 int unshare(int flags);● setns(): 将进程attach到一个已经存在的namespace里面。 int setns(int fd, int nstype);● 参数fd表示我们要加入的namespace的文件描述符。如:/proc/[pid]/ns下面对应的文件描述符。 ● 参数nstype让调用者可以去检查fd指向的namespace类型是否符合我们实际的要求。如果填0表示不检查。 namespace 实践 为了最好的体验还是在 Linux 内核 3.8 以上的系统上进行这里使用的 Ubuntu 20.04.2, kernel版本5.4.0-182-generic。为什么不用 docker for windows 或者 docker for mac 呢因为这两个其实还是是在 linux 虚拟机上运行 docker 的docker for windows 需要将 linux 虚拟机装在开启 hyper-v 的 win10 专业版上而 docker for mac 使用通过 HyperKit 运行 linux 虚拟机。为了方便使用 c语言代码 来演示循序渐进的达到 Docker 的体验。 UTS Namespace UTS namespace提供了主机名和域名的隔离这样每一个容器就可以拥有独立的主机名和域名在网络上可以被视为一个独立的节点而非宿主机上的一个进程。 下面让我们来看下UTS的隔离效果测试代码如下: #define _GNU_SOURCE #include sys/types.h #include sys/wait.h #include stdio.h #include sched.h #include signal.h #include unistd.h#define STACK_SIZE (1024*1024)static char child_stack[STACK_SIZE]; char* const child_args[] {/bin/bash,NULL };int child_main(void* args){printf(in child process!\n);sethostname(changed namespace, 12);execv(child_args[0], child_args);return 1; }int main(){printf(program begin: \n);int child_pid clone(child_main, child_stack STACK_SIZE, SIGCHLD|CLONE_NEWUTS, NULL);waitpid(child_pid, NULL, 0);printf(quit\n);return 0; }主要是main中在调用clone函数创建新进程及新namespace的时候传递了CLONE_NEWUTS flag用于对主机名和域名的隔离。 如果没有gcc需要先安装gcc环境 编译并运行程序会发现主机名发生了变化。 rootdouble:~# gcc -Wall uts.c -o uts ./uts program begin: in child process! rootchanged name:~# hostname changed name rootchanged name:~# exit exit quit 每个容器的主机名不同就是使用UTS Namespace机制实现的。 IPC Namespace 容器中进程间的通信采用的方式包括: 信号量消息队列和共享内存。与虚拟机不同的是容器内部进程间通信对宿主机来说实际上是具有相同的PID namespace中的进程间通信因此需要一个而唯一的标识符来进行区别。申请IPC资源就申请了这样一个全局唯一的32位ID所以IPC namespace中实际上包含了系统IPC标识符以及实现POSIX消息队列的文件系统。在同一个IPC namespace下的进程彼此可见而与其他的IPC namespace下的进程则互相不可见。 下面我们来看下IPC的隔离效果测试代码如下: #define _GNU_SOURCE #include sys/types.h #include sys/wait.h #include stdio.h #include sched.h #include signal.h #include unistd.h#define STACK_SIZE (1024*1024)static char child_stack[STACK_SIZE]; char* const child_args[] {/bin/bash,NULL };int child_main(void* args){printf(in child process!\n);sethostname(changed namespace, 12);execv(child_args[0], child_args);return 1; }int main(){printf(program begin: \n);int child_pid clone(child_main, child_stack STACK_SIZE, SIGCHLD | CLONE_NEWUTS | CLONE_NEWIPC, NULL);waitpid(child_pid, NULL, 0);printf(quit\n);return 0; }main函数中调用clone函数创建新进程同时创建新namespaces的时候传递CLONE_NEWIPCflag, 来实现进程间IPC的隔离。 在运行程序的时候为了方便测试进程间通信是否被真正的隔离了 1.  首先我们先使用ipcmk -Q命令创建一个queue: rootdouble:~# ipcmk -Q Message queue id: 02.  使用ipcs -q查看queue是否创建成功: rootdouble:~# ipcs -q------ Message Queues -------- key msqid owner perms used-bytes messages 0xe594be1e 0 root 644 0 0 3.  编译并运行ipc.c代码对IPC进行隔离并进行验证: rootdouble:~# gcc -Wall ipc.c -o ipc ./ipc program begin: in child process! rootchanged name:~# ipcs -q------ Message Queues -------- key msqid owner perms used-bytes messages 从运行的结果来看已经找不到原先声明的message queue实现了IPC的隔离。 PID Namespace PID namespace隔离非常实用它对进程PID重新标号,即两个不同的namespace下的进程可以拥有同一个PID。每一个PID namespace都有字的计数程序。内核为所有的PID namespace维护了一个树状结构最顶层的是系统初始时创建的,即root namespace。他创建的新的PID namespace称child namespace。通过这种方式不同的PID namespace会形成一个等级的体系。所属的父节点可以看到子节点中的进程并可以通过信号等方式对子节点中的进程产生影响。反过来子节点不能看到父节点PID namespace中的任何内容。 由此产生如下结论 ● 每个PID namespace中的第一个进程“PID 1“都会像传统Linux中的init进程一样拥有特权起特殊作用。 ● 一个namespace中的进程不可能通过kill或ptrace影响父节点或者兄弟节点中的进程因为其他节点的PID在这个namespace中没有任何意义。 ● 如果你在新的PID namespace中重新挂载/proc文件系统会发现其下只显示同属一个PID namespace中的其他进程。 ● 在root namespace中可以看到所有的进程并且递归包含所有子节点中的进程。 ●  下面我们来看下对PID的隔离效果测试代码如下: #define _GNU_SOURCE #include sys/types.h #include sys/wait.h #include stdio.h #include sched.h #include signal.h #include unistd.h#define STACK_SIZE (1024*1024)static char child_stack[STACK_SIZE]; char* const child_args[] {/bin/bash,NULL };int child_main(void* args){printf(in child process!\n);sethostname(changed namespace, 12);execv(child_args[0], child_args);return 1; }int main(){printf(program begin: \n);int child_pid clone(child_main, child_stack STACK_SIZE, SIGCHLD | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID, NULL);waitpid(child_pid, NULL, 0);printf(quit\n);return 0; }main函数中调用clone函数创建新的进程同时创建新的namespace的时候传递CLONE_NEWPID flag。来实现对PIDg隔离。 让我们编译并运行代码看下效果 rootdouble:~# vi pid.c rootdouble:~# gcc -Wall pid.c -o pid ./pid program begin: in child process! rootchanged name:~# echo $$ 1 rootchanged name:~# ps aux 我们可以看到子进程的pid是1了但是我们会发现在子进程的shell里输入ps,top等命令我们还是可以看得到所有进程。说明并没有完全隔离。这是因为像ps, top这些命令会去读/proc文件系统所以因为/proc文件系统在父进程和子进程都是一样的所以这些命令显示的东西都是一样的。 所以我们还需要对文件系统进行隔离。 Mount Namespace Mount namespace通过隔离文件系统挂载点对隔离文件系统提供支持。隔离后不同的mount namespace中的文件结构发生变化也互不影响。你可以通过/proc/[pid]/mounts查看到所有挂载在当前namesapce中的文件系统还可以通过/proc/[pid]/mountstats看到mount namespace中文件设备的统计信息包括挂载的文件名称文件系统类型挂载位置等等。 进程在创建mount namespace的时候会把当前结构复制给新的namespace。 新的namespace中的所有mount操作都影响自身的文件系统而对外界不会产生任何影响。这样做就严格地实现了隔离。 让我们来对文件系统进行隔离测试的代码如下: #define _GNU_SOURCE #include sys/types.h #include sys/wait.h #include sys/mount.h #include stdio.h #include sched.h #include signal.h #include unistd.h#define STACK_SIZE (1024 * 1024) // sync primitive int checkpoint[2]; static char child_stack[STACK_SIZE]; char* const child_args[] {/bin/bash,NULL };int child_main(void* arg) {char c;// init sync primitiveclose(checkpoint[1]);// setup hostnamesethostname(changed namespace, 12);// remount /proc to get accurate top ps outputmount(proc, /proc, proc, 0, NULL);// wait...read(checkpoint[0], c, 1);execv(child_args[0], child_args);printf(Ooops\n);return 1; } int main() {// init sync primitivepipe(checkpoint);int child_pid clone(child_main, child_stackSTACK_SIZE,CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, NULL);// further init here (nothing yet)// signal doneclose(checkpoint[1]);waitpid(child_pid, NULL, 0);printf(quit!\n);return 0; }main函数中调用clone函数创建新进程同时创建新的namespace时需要增加CLONE_NEWNS flag。来实现对Mount namespace的隔离。 下面让我们编译并运行下程序来验证是否实现了对文件系统的隔离。 rootdouble:~# gcc -Wall mntns.c -o mnt ./mnt rootchanged name:~# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.2 9836 3952 pts/2 S 18:08 0:00 /bin/bash root 8 0.0 0.1 11488 3288 pts/2 R 18:08 0:00 ps aux上面我们可以看到只有两个进程 而且pid1的进程是我们的/bin/bash。我们还可以看到/proc目录下也干净了很多 rootchanged name:~# ls /proc 1 bus cpuinfo dma filesystems ioports keys kpagecount mdstat mounts partitions scsi stat sysvipc uptime vmstat 9 cgroups crypto driver fs irq key-users kpageflags meminfo mtrr pressure self swaps thread-self version zoneinfo acpi cmdline devices execdomains interrupts kallsyms kmsg loadavg misc net sched_debug slabinfo sys timer_list version_signature buddyinfo consoles diskstats fb iomem kcore kpagecgroup locks modules pagetypeinfo schedstat softirqs sysrq-trigger tty vmallocinfo 关于mount相关的知识很多。这里就具体的详细介绍了如果感兴趣可以看下: Mount namespaces and shared subtrees mount a filesystem User Namespace 注意:User namespace是Linux内核(Linux 3.8)最后支持的namespace所以有的版本的系统内核可能还没有对该namespace支持。 User namespace主要隔离了安全相关的标识符和属性包括用户ID,用户组ID,root目录等。通俗点就是: 一个普通用户的进程通过clone()创建新的进程在新user namespace中可以拥有不同的用户和用户组。这意味着一个进程在容器外属于一个没有特殊权限的普通用户但是它创建的容器进程却属于拥有所有权限的超级用户这个技术为容器提供了极大的自由。 Linux中特权用户的user ID是0演示的最终我们将看到user ID非0的进程启动user namespace后user ID可以变为0。使用user namespace的方法和其它的namespace的使用方式没有太大的区别。即调用clone()的时候需要加入CLONE_NEWUSER标识位。 让我们来看下user namespace的隔离效果测试代码如下: #define _GNU_SOURCE #include stdio.h #include stdlib.h #include sys/types.h #include sys/wait.h #include sys/mount.h #include sys/capability.h #include stdio.h #include sched.h #include signal.h #include unistd.h#define STACK_SIZE (1024 * 1024)static char container_stack[STACK_SIZE]; char* const container_args[] {/bin/bash,NULL };int pipefd[2];void set_map(char* file, int inside_id, int outside_id, int len) {FILE* mapfd fopen(file, w);if (NULL mapfd) {perror(open file error);return;}fprintf(mapfd, %d %d %d, inside_id, outside_id, len);fclose(mapfd); }void set_uid_map(pid_t pid, int inside_id, int outside_id, int len) {char file[256];sprintf(file, /proc/%d/uid_map, pid);set_map(file, inside_id, outside_id, len); }void set_gid_map(pid_t pid, int inside_id, int outside_id, int len) {char file[256];sprintf(file, /proc/%d/gid_map, pid);set_map(file, inside_id, outside_id, len); }int container_main(void* arg) { printf(Container [%5d] - inside the container!\n, getpid()); printf(Container: eUID %ld; eGID %ld, UID%ld, GID%ld\n,(long) geteuid(), (long) getegid(), (long) getuid(), (long) getgid()); /* 等待父进程通知后再往下执行进程间的同步 */char ch;close(pipefd[1]);read(pipefd[0], ch, 1); printf(Container [%5d] - setup hostname!\n, getpid());//set hostnamesethostname(container,10); //remount /proc to make sure the top and ps show containers informationmount(proc, /proc, proc, 0, NULL); execv(container_args[0], container_args);printf(Somethings wrong!\n);return 1; }int main() {const int gidgetgid(), uidgetuid(); printf(Parent: eUID %ld; eGID %ld, UID%ld, GID%ld\n,(long) geteuid(), (long) getegid(), (long) getuid(), (long) getgid()); pipe(pipefd); printf(Parent [%5d] - start a container!\n, getpid()); int container_pid clone(container_main, container_stackSTACK_SIZE, CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUSER | SIGCHLD, NULL); printf(Parent [%5d] - Container [%5d]!\n, getpid(), container_pid); //To map the uid/gid, // we need edit the /proc/PID/uid_map (or /proc/PID/gid_map) in parent//The file format is// ID-inside-ns ID-outside-ns length//if no mapping, // the uid will be taken from /proc/sys/kernel/overflowuid// the gid will be taken from /proc/sys/kernel/overflowgidset_uid_map(container_pid, 0, uid, 1);set_gid_map(container_pid, 0, gid, 1); printf(Parent [%5d] - user/group mapping done!\n, getpid()); /* 通知子进程 */close(pipefd[1]); waitpid(container_pid, NULL, 0);printf(Parent - container stopped!\n);return 0; }在编译并执行代码之前我们先来看下当前的用户uid和gid.(需以普通用户执行) $ id uid1000(double) gid1000(double) groups1000(double)现在编译并运行我们的代码来验证user namespace是否隔离成功 注意: 如果编译时如下报错: $ gcc userns.c -Wall -lcap -o userns ./userns userns.c:7:10: fatal error: sys/capability.h: No such file or directory7 | #include sys/capability.h| ^~~~~~~~~~~~~~~~~~ compilation terminated. 则在ubuntu编译则需要安装libcap-dev包,如果在centos上编译则需要安装libcap-devel包。 重新执行 $ gcc userns.c -Wall -lcap -o userns ./userns Parent: eUID 1000; eGID 1000, UID1000, GID1000 Parent [ 9527] - start a container! Parent [ 9527] - Container [ 9528]! Parent [ 9527] - user/group mapping done! Container [ 1] - inside the container! Container: eUID 0; eGID 65534, UID0, GID65534 Container [ 1] - setup hostname!我们可以看到容器里的用户和命令行提示符是root用户了 rootcontainer:~# id uid0(root) gid65534(nogroup) groups65534(nogroup)Network Namespace 总结 容器的隔离实现基本就是通过Linux内核提供的这6种namespace实现。但是容器依旧没有实现完全的环境隔离。比如: SELinuxCgroups以及/sys/proc/sys, /dev/sd*等目录下的资源依据是没有被隔离的。因此我们通常使用的ps top命令查看到的数据依旧是宿主机的数据。因为它们的数据来源于/proc等目录下的文件。如果想要在可视化的角度来实现这方便的可视化隔离。可以看看之前调研的lxcfs对docker容器隔离。 参考 浅谈 Linux Namespace | xigangs home Docker基础技术Linux Namespace下 | 酷 壳 - CoolShell http://docs.wixstatic.com/ugd/295986_d73d8d6087ed430c34c21f90b0b607fd.pdf http://ramirose.wixsite.com/ramirosen Docker背后的内核知识——Namespace资源隔离_语言 开发_孙健波_InfoQ精选文章 Linux Namespace分析——mnt namespace的实现与应用 Linux内核的namespace机制分析 - kk Blog —— 通用基础

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/88923.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站建设的文章php网站代做

‍ 嘉诚信息案例 本项目案例由嘉诚信息投递并参与数据猿与上海大数据联盟联合推出的《2024中国数智化转型升级创新服务企业》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 随着信息时代的迅猛发展,消防人员正面临前所未有的知识爆炸挑战。为了高…

西部数码做的网站打不开python如何与wordpress

Flink 中的时间语义 时间语义: EventTime:事件创建时间;Ingestion Time:数据进入Flink的时间;Processing Time:执行操作算子的本地系统时间,与机器无关。不同的时间语义有不同的应用场合&#x…

如何创建微信小程序商城新网站应该怎么做seo

用lambda表达式实现Runnable lambda表达式替换了原来匿名内部类的写法,没有了匿名内部类繁杂的代码实现,而是突出了,真正的处理代码。最好的示例就是 实现Runnable 的线程实现方式了: 用() -> {}代码块替代了整个匿名内部类 Test public …

推荐系统网站开发企业门户网站 php

所需文件xampp 集成服务器(本文使用Apache2.4MySQLPHP7.4.3)vscodeXdebugphp-debug 插件配置Xdebug1. 下载Xdebug插件 (直接去 https://xdebug.org/download.php下载php对应版本的插件)如果不知道如何选取版本,则如下Step 1:获取本地php版本信息 (利用ph…

白名单 网站什么网站可以做美食

项目背景 在全球经济发展的大背景下,矿产资源作为工业的“粮食”和“血液”,其合理开发与有效管理对于国家的经济发展、能源安全和工业稳定供应具有不可替代的作用。然而,随着资源的日益紧张和环境保护要求的提高,传统的矿产资源…

口碑好的网站建设方法有哪些服装网站搭建计划书

前段时间编译一个引用自己写的静态库的程序时老是出现链接时的多个重定义的错误,而自己的代码明明没有重定义这些东西,譬如: LIBCMT.lib(_file.obj) : error LNK2005: ___initstdio already defined in libc.lib(_file.obj) LIBCMT.lib(_fi…

成品网站速成网站网站开发用什么后端框架

介绍一个酷炫的目标检测方式: 论文:https://arxiv.org/abs/2401.17270 代码:https://github.com/AILab-CVC/YOLO-World 文章目录 摘要Introduction第2章 相关工作2.1 传统目标检测2.2 开放词汇目标检测 第3章 方法3.1 预训练公式&#xff1a…

容桂网站制作价位柳州建站

计算机速度可能每年都在提高,但如果用光脉冲而不是电流来代表它的二进制代码1和0,将给计算速度带来质的飞跃。据每日科学网9月10日报道,美国宾夕法尼亚大学研究人员用硫化镉纳米线制造出了第一个全光光子开关,并将其与逻辑门结合&…

网站商城系统设计南京微信小程序开发制作

产品概述 低功耗墒情监测站基于传感、无线通信、处理与控制等物联网技术的开发,利用传感技术,通过传感器测量土壤墒情,并使用物联网进行传输。无需专门的通信线路,在联网的状态下,数据可快速、主动的上报到云平台&…

手机设计软件哪个好googleseo优化

没有完全不含亚硫酸盐的葡萄酒,有机葡萄酒和生物动力葡萄酒中也会含有少量天然 亚硫酸盐。因为它是在发酵过程中产生的一种化合物,所以不可能酿造无亚硫酸盐的葡萄酒。 在大多数葡萄酒国家都有葡萄酒法律规定,如果葡萄酒超过特定的亚硫酸盐水…

企业门户网站制作价格怎么算做的网站老被攻击

JQuery是继prototype之后又一个优秀的Javascript库。它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0, FF 1.5, Safari 2.0, Opera 9.0),jQuery2.0及后续版本将不再支持IE6/7/8浏览器。jQuery使用户能更方便地处理HTML(标准通用标记语…

郑州网站及优化三只小猪的题目登网站做

简介 Java 类文件反汇编工具(javap)是一个命令行工具,用于反汇编一个或多个 Java 类文件。反汇编的输出内容取决于使用的选项。当不使用任何选项时,javap 命令将打印传递给它的类的包、受保护的和公共字段以及方法。javap 命令将其…

东营市报名系统网站设计公司沈阳网站 房小二

当我在控制面板的卸载软件里没有发现我要删软件的软件时,只找到了软件的部分安装目录删除,就会发生残留问题,导致软件依旧可以运行。 经过这么多次后,我就找到了我自认为的最优解。首先运行这个软件;之后打开windows任…

网站设计与制作报价北京专业网站优化

本来是很简单的一道题,却想了好长时间 由于数据量比较大,所以逐行读入,逐行处理 先处理每一行的不相邻元素和的最大值,记录在数组b中 最后计算不相邻行的和的最大值 二者的状态转移方程都类似:dp[j] max(dp[j - 1], d…

如何仿别人网站的莫板东莞餐饮网站建设

Go 语言提供了数组类型的数据结构。 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。 相对于去声明 number0, number1, ..., number99 的变量,使用数组形式 numbers[0], num…

个人网站做装修可以吗wordpress右侧空白

在上一篇的文章中,测试验证了如何安装Oracle23c free版本的数据库。总体上来说还是比较简单的。把相关的依赖包安装好,rpm -ivh执行安装即可。 在这一篇文章中将验证测试如何卸载。Oracle的文档介绍就是强大,我们找到文档内容,按…

网站小程序logo设计免费设计

官网:http://element-cn.eleme.io/#/zh-CN 转载于:https://www.cnblogs.com/weibanggang/p/9995433.html

东莞微信网站建设更好网站案例分析湖南

安全点是jvm选来进行GC的线程中断点。线程在执行到安全点后询问GC标志位,若标志位标识将要进行GC,则程序主动中断挂起线程等待GC。安全点的选定基本上是根据"是否具有让程序长时间执行的特征"为标准进行选定的。目前会产生安全点的主要有&…

新网站怎么做才能让搜狗收录北京建设网站网站

缩短JDK发布周期的原因之一是有可能推出更快的安全错误修复和增强功能。 在本文中,我们将简要回顾一下最新JDK版本中引入的主要安全增强功能。 由于这些增强功能中的大多数与TLS相关,因此必须了解TLS握手过程,如下图所示: JDK 9 …

asp网站如何发布河南网站建设公司

Go 编译构建的一些细节 发现自己竟然没有怎么认真研究过 go 的编译构建命令。 结论前置 go run 专门用来运行命令源码文件的命令,一般用来运行单个文件go build 主要是用于测试编译。编译某个包或者项目,在当前目录下生成可执行文件go install 编译并…