返回顶部
首页 > 资讯 > 操作系统 >怎么在Linux上用strace来理解系统调用
  • 672
分享到

怎么在Linux上用strace来理解系统调用

2023-06-16 06:06:32 672人浏览 八月长安
摘要

本篇内容介绍了“怎么在linux上用strace来理解系统调用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!使用 strace 跟踪用户进程

本篇内容介绍了“怎么在linux上用strace来理解系统调用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

使用 strace 跟踪用户进程和 Linux 内核之间的交互。

系统调用system call是程序从内核请求服务的一种编程方式,而 strace 是一个功能强大的工具,可让你跟踪用户进程与 Linux 内核之间的交互。

要了解操作系统的工作原理,首先需要了解系统调用的工作原理。操作系统的主要功能之一是为用户程序提供抽象机制。

操作系统可以大致分为两种模式:

  • 内核模式:操作系统内核使用的一种强大的特权模式

  • 用户模式:大多数用户应用程序运行的地方    用户大多使用命令行实用程序和图形用户界面(GUI)来执行日常任务。系统调用在后台静默运行,与内核交互以完成工作。

系统调用与函数调用非常相似,这意味着它们都接受并处理参数然后返回值。唯一的区别是系统调用进入内核,而函数调用不进入。从用户空间切换到内核空间是使用特殊的 trap 机制完成的。

通过使用系统库(在 Linux 系统上又称为 glibc),大部分系统调用对用户隐藏了。尽管系统调用本质上是通用的,但是发出系统调用的机制在很大程度上取决于机器(架构)。

本文通过使用一些常规命令并使用 strace 分析每个命令进行的系统调用来探索一些实际示例。这些示例使用 Red Hat Enterprise Linux,但是这些命令运行在其他 Linux 发行版上应该也是相同的:

[root@sandbox ~]# cat /etc/redhat-releaseRed Hat Enterprise Linux Server release 7.7 (Maipo)[root@sandbox ~]#[root@sandbox ~]# uname -r3.10.0-1062.el7.x86_64[root@sandbox ~]#

首先,确保在系统上安装了必需的工具。你可以使用下面的 rpm 命令来验证是否安装了 strace。如果安装了,则可以使用 -V 选项检查 strace 实用程序的版本号:

[root@sandbox ~]# rpm -qa | grep -i stracestrace-4.12-9.el7.x86_64[root@sandbox ~]#[root@sandbox ~]# strace -Vstrace -- version 4.12[root@sandbox ~]#

如果没有安装,运行命令安装:

yum install strace

出于本示例的目的,在 /tmp 中创建一个测试目录,并使用 touch 命令创建两个文件:

[root@sandbox ~]# cd /tmp/[root@sandbox tmp]#[root@sandbox tmp]# mkdir testdir[root@sandbox tmp]#[root@sandbox tmp]# touch testdir/file1[root@sandbox tmp]# touch testdir/file2[root@sandbox tmp]#

(我使用 /tmp 目录是因为每个人都可以访问它,但是你可以根据需要选择另一个目录。)

testdir 目录下使用 ls 命令验证该文件已经创建:

[root@sandbox tmp]# ls testdir/file1  file2[root@sandbox tmp]#

你可能每天都在使用 ls 命令,而没有意识到系统调用在其下面发挥的作用。抽象地来说,该命令的工作方式如下:

命令行工具 -> 从系统库(glibc)调用函数 -> 调用系统调用

ls 命令内部从 Linux 上的系统库(即 glibc)调用函数。这些库去调用完成大部分工作的系统调用。

如果你想知道从 glibc 库中调用了哪些函数,请使用 ltrace 命令,然后跟上常规的 ls testdir/命令:

ltrace ls testdir/

如果没有安装 ltrace,键入如下命令安装:

yum install ltrace

大量的输出会被堆到屏幕上;不必担心,只需继续就行。ltrace 命令输出中与该示例有关的一些重要库函数包括:

opendir("testdir/")                                  = { 3 }readdir({ 3 })                                       = { 101879119, "." }readdir({ 3 })                                       = { 134, ".." }readdir({ 3 })                                       = { 101879120, "file1" }strlen("file1")                                      = 5memcpy(0x1665be0, "file1\0", 6)                      = 0x1665be0readdir({ 3 })                                       = { 101879122, "file2" }strlen("file2")                                      = 5memcpy(0x166dcb0, "file2\0", 6)                      = 0x166dcb0readdir({ 3 })                                       = nilclosedir({ 3 })

通过查看上面的输出,你或许可以了解正在发生的事情。opendir 库函数打开一个名为 testdir 的目录,然后调用 readdir 函数,该函数读取目录的内容。最后,有一个对 closedir 函数的调用,该函数将关闭先前打开的目录。现在请先忽略其他 strlenmemcpy 功能。

你可以看到正在调用哪些库函数,但是本文将重点介绍由系统库函数调用的系统调用。

与上述类似,要了解调用了哪些系统调用,只需将 strace 放在 ls testdir 命令之前,如下所示。 再次,一堆乱码丢到了你的屏幕上,你可以按照以下步骤进行操作:

[root@sandbox tmp]# strace ls testdir/execve("/usr/bin/ls", ["ls", "testdir/"], []) = 0brk(NULL)                               = 0x1f12000<<< truncated strace output >>>write(1, "file1  file2\n", 13file1  file2)          = 13close(1)                                = 0munmap(0x7fd002c8d000, 4096)            = 0close(2)                                = 0exit_group(0)                           = ?+++ exited with 0 +++[root@sandbox tmp]#

运行 strace 命令后屏幕上的输出就是运行 ls 命令的系统调用。每个系统调用都为操作系统提供了特定的用途,可以将它们大致分为以下几个部分:

  • 进程管理系统调用

  • 文件管理系统调用

  • 目录和文件系统管理系统调用

  • 其他系统调用

分析显示到屏幕上的信息的一种更简单的方法是使用 strace 方便的 -o 标志将输出记录到文件中。在 -o 标志后添加一个合适的文件名,然后再次运行命令:

[root@sandbox tmp]# strace -o trace.log ls testdir/file1  file2[root@sandbox tmp]#

这次,没有任何输出干扰屏幕显示,ls 命令如预期般工作,显示了文件名并将所有输出记录到文件 trace.log 中。仅仅是一个简单的 ls 命令,该文件就有近 100 行内容:

[root@sandbox tmp]# ls -l trace.log-rw-r--r--. 1 root root 7809 Oct 12 13:52 trace.log[root@sandbox tmp]#[root@sandbox tmp]# wc -l trace.log114 trace.log[root@sandbox tmp]#

让我们看一下这个示例的 trace.log 文件的第一行:

execve("/usr/bin/ls", ["ls", "testdir/"], []) = 0
  • 该行的第一个单词 execve 是正在执行的系统调用的名称。

  • 括号内的文本是提供给该系统调用的参数。

  • 符号 = 后的数字(在这种情况下为 0)是 execve 系统调用的返回值。

现在的输出似乎还不太吓人,对吧。你可以应用相同的逻辑来理解其他行。

现在,将关注点集中在你调用的单个命令上,即 ls testdir。你知道命令 ls 使用的目录名称,那么为什么不在 trace.log 文件中使用 grep 查找 testdir 并查看得到的结果呢?让我们详细查看一下结果的每一行:

[root@sandbox tmp]# grep testdir trace.logexecve("/usr/bin/ls", ["ls", "testdir/"], []) = 0stat("testdir/", {st_mode=S_IFDIR|0755, st_size=32, ...}) = 0openat(AT_FDCWD, "testdir/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3[root@sandbox tmp]#

回顾一下上面对 execve 的分析,你能说一下这个系统调用的作用吗?

execve("/usr/bin/ls", ["ls", "testdir/"], []) = 0

你无需记住所有系统调用或它们所做的事情,因为你可以在需要时参考文档。手册页可以解救你!在运行 man 命令之前,请确保已安装以下软件包:

[root@sandbox tmp]# rpm -qa | grep -i man-pagesman-pages-3.53-5.el7.noarch[root@sandbox tmp]#

请记住,你需要在 man 命令和系统调用名称之间添加 2。如果使用 man man 阅读 man 命令的手册页,你会看到第 2 节是为系统调用保留的。同样,如果你需要有关库函数的信息,则需要在 man 和库函数名称之间添加一个 3

以下是手册的章节编号及其包含的页面类型:

  • 1:可执行的程序或 shell 命令

  • 2:系统调用(由内核提供的函数)

  • 3:库调用(在程序的库内的函数)

  • 4:特殊文件(通常出现在 /dev

使用系统调用名称运行以下 man 命令以查看该系统调用的文档:

man 2 execve

按照 execve 手册页,这将执行在参数中传递的程序(在本例中为 ls)。可以为 ls 提供其他参数,例如本例中的 testdir。因此,此系统调用仅以 testdir 作为参数运行 ls

execve - execute program DESCRIPTION       execve()  executes  the  program  pointed to by filename

下一个系统调用,名为 stat,它使用 testdir 参数:

stat("testdir/", {st_mode=S_IFDIR|0755, st_size=32, ...}) = 0

使用 man 2 stat 访问该文档。stat 是获取文件状态的系统调用,请记住,Linux 中的一切都是文件,包括目录。

接下来,openat 系统调用将打开 testdir。密切注意返回的 3。这是一个文件描述符,将在以后的系统调用中使用:

openat(AT_FDCWD, "testdir/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3

到现在为止一切都挺好。现在,打开 trace.log 文件,并转到 openat 系统调用之后的行。你会看到 getdents 系统调用被调用,该调用完成了执行 ls testdir 命令所需的大部分操作。现在,从 trace.log 文件中用 grep 获取 getdents

[root@sandbox tmp]# grep getdents trace.loggetdents(3, , 32768)     = 112getdents(3, , 32768)     = 0[root@sandbox tmp]#

getdents 的手册页将其描述为 “获取目录项”,这就是你要执行的操作。注意,getdents 的参数是 3,这是来自上面 openat 系统调用的文件描述符。

现在有了目录列表,你需要一种在终端中显示它的方法。因此,在日志中用 grep 搜索另一个用于写入终端的系统调用 write

[root@sandbox tmp]# grep write trace.logwrite(1, "file1  file2\n", 13)          = 13[root@sandbox tmp]#

在这些参数中,你可以看到将要显示的文件名:file1file2。关于第一个参数(1),请记住在 Linux 中,当运行任何进程时,默认情况下会为其打开三个文件描述符。以下是默认的文件描述符:

  • 0:标准输入

  • 1:标准输出

  • 2:标准错误

因此,write 系统调用将在标准显示(就是这个终端,由 1 所标识的)上显示 file1file2

现在你知道哪个系统调用完成了 ls testdir/ 命令的大部分工作。但是在 trace.log 文件中其它的 100 多个系统调用呢?操作系统必须做很多内务处理才能运行一个进程,因此,你在该日志文件中看到的很多内容都是进程初始化和清理。阅读整个 trace.log 文件,并尝试了解 ls 命令是怎么工作起来的。

既然你知道了如何分析给定命令的系统调用,那么就可以将该知识用于其他命令来了解正在执行哪些系统调用。strace 提供了许多有用的命令行标志,使你更容易使用,下面将对其中一些进行描述。

默认情况下,strace 并不包含所有系统调用信息。但是,它有一个方便的 -v 冗余选项,可以在每个系统调用中提供附加信息:

strace -v ls testdir

在运行 strace 命令时始终使用 -f 选项是一种好的作法。它允许 strace 对当前正在跟踪的进程创建的任何子进程进行跟踪:

strace -f ls testdir

假设你只需要系统调用的名称、运行的次数以及每个系统调用花费的时间百分比。你可以使用 -c 标志来获取这些统计信息:

strace -c ls testdir/

假设你想专注于特定的系统调用,例如专注于 open 系统调用,而忽略其余部分。你可以使用-e 标志跟上系统调用的名称:

[root@sandbox tmp]# strace -e open ls testdiropen("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3open("/lib64/libcap.so.2", O_RDONLY|O_CLOEXEC) = 3open("/lib64/libacl.so.1", O_RDONLY|O_CLOEXEC) = 3open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3open("/lib64/libattr.so.1", O_RDONLY|O_CLOEXEC) = 3open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3open("/usr/lib/locale/locale-arcHive", O_RDONLY|O_CLOEXEC) = 3file1  file2+++ exited with 0 +++[root@sandbox tmp]#

如果你想关注多个系统调用怎么办?不用担心,你同样可以使用 -e 命令行标志,并用逗号分隔开两个系统调用的名称。例如,要查看 writegetdents 系统调用:

[root@sandbox tmp]# strace -e write,getdents ls testdirgetdents(3, , 32768)     = 112getdents(3, , 32768)     = 0write(1, "file1  file2\n", 13file1  file2)          = 13+++ exited with 0 +++[root@sandbox tmp]#

到目前为止,这些示例是明确地运行的命令进行了跟踪。但是,要跟踪已经运行并正在执行的命令又怎么办呢?例如,如果要跟踪用来长时间运行进程的守护程序,该怎么办?为此,strace 提供了一个特殊的 -p 标志,你可以向其提供进程 ID。

我们的示例不在守护程序上运行 strace,而是以 cat 命令为例,如果你将文件名作为参数,通常 cat 会显示文件的内容。如果没有给出参数,cat 命令会在终端上等待用户输入文本。输入文本后,它将重复给定的文本,直到用户按下 Ctrl + C 退出为止。

从一个终端运行 cat 命令;它会向你显示一个提示,并等待在那里(记住 cat 仍在运行且尚未退出):

[root@sandbox tmp]# cat

在另一个终端上,使用 ps 命令找到进程标识符(PID):

[root@sandbox ~]# ps -ef | grep catroot      22443  20164  0 14:19 pts/0    00:00:00 catroot      22482  20300  0 14:20 pts/1    00:00:00 grep --color=auto cat[root@sandbox ~]#

现在,使用 -p 标志和 PID(在上面使用 ps 找到)对运行中的进程运行 strace。运行 strace 之后,其输出说明了所接驳的进程的内容及其 PID。现在,strace 正在跟踪 cat 命令进行的系统调用。看到的第一个系统调用是 read,它正在等待文件描述符 0(标准输入,这是运行 cat 命令的终端)的输入:

[root@sandbox ~]# strace -p 22443strace: Process 22443 attachedread(0,

现在,返回到你运行 cat 命令的终端,并输入一些文本。我出于演示目的输入了 x0x0。注意 cat 是如何简单地重复我输入的内容的。因此,x0x0 出现了两次。我输入了第一个,第二个是 cat 命令重复的输出:

[root@sandbox tmp]# catx0x0x0x0

返回到将 strace 接驳到 cat 进程的终端。现在你会看到两个额外的系统调用:较早的 read 系统调用,现在在终端中读取 x0x0,另一个为 write,它将 x0x0 写回到终端,然后是再一个新的 read,正在等待从终端读取。请注意,标准输入(0)和标准输出(1)都在同一终端中:

[root@sandbox ~]# strace -p 22443strace: Process 22443 attachedread(0, "x0x0\n", 65536)                = 5write(1, "x0x0\n", 5)                   = 5read(0,

想象一下,对守护进程运行 strace 以查看其在后台执行的所有操作时这有多大帮助。按下 Ctrl + C 杀死 cat 命令;由于该进程不再运行,因此这也会终止你的 strace 会话。

如果要查看所有的系统调用的时间戳,只需将 -t 选项与 strace 一起使用:

[root@sandbox ~]#strace -t ls testdir/ 14:24:47 execve("/usr/bin/ls", ["ls", "testdir/"], []) = 014:24:47 brk(NULL)                      = 0x1f0700014:24:47 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2530bc800014:24:47 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)14:24:47 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3

如果你想知道两次系统调用之间所花费的时间怎么办?strace 有一个方便的 -r 命令,该命令显示执行每个系统调用所花费的时间。非常有用,不是吗?

[root@sandbox ~]#strace -r ls testdir/ 0.000000 execve("/usr/bin/ls", ["ls", "testdir/"], []) = 00.000368 brk(NULL)                 = 0x19660000.000073 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb6b11550000.000047 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)0.000119 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3

“怎么在Linux上用strace来理解系统调用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: 怎么在Linux上用strace来理解系统调用

本文链接: https://lsjlt.com/news/282504.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 怎么在Linux上用strace来理解系统调用
    本篇内容介绍了“怎么在Linux上用strace来理解系统调用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!使用 strace 跟踪用户进程...
    99+
    2023-06-16
  • Linux系统调试工具strace怎么用
    这篇文章主要讲解了“Linux系统调试工具strace怎么用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Linux系统调试工具strace怎么用”吧!1、简介strace是Linux系统中...
    99+
    2023-06-28
  • strace命令怎么在Linux系统中使用
    strace命令怎么在Linux系统中使用?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1.strace简介strace常用来跟踪进程执行时的系统调用和所接收的信号。 通过st...
    99+
    2023-06-09
  • 怎么在linux系统中使用strace命令
    这期内容当中小编将会给大家带来有关怎么在linux系统中使用strace命令,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。调用:strace [ -dffhiqrtttTvxx ] [ -acolumn ...
    99+
    2023-06-10
  • 详解linux系统调用原理
    操作系统通过系统调用为运行于其上的进程提供服务。 当用户态进程发起一个系统调用, CPU 将切换到 内核态 并开始执行一个 内核函数 。 内核函数负责响应应用程序的要求,例如操作文件、进行网络通讯或者申请内存资源等。 举...
    99+
    2022-06-04
    linux 调用
  • 如何在Linux系统上使用Git来管理Go语言项目?
    在现代软件开发中,版本控制系统是一个必不可少的工具。其中,Git是最受欢迎的版本控制系统之一。它允许开发人员协同工作,管理代码变更,并跟踪项目历史记录。同时,Go语言也是一个非常流行的编程语言,因为它具有高效、简洁和易于学习的特点。在本文中...
    99+
    2023-10-12
    linux git django
  • 怎么用gtf来调整Linux系统中分辩率问题
    本篇内容介绍了“怎么用gtf来调整Linux系统中分辩率问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!当我们用Linux的桌面环境的时候...
    99+
    2023-06-13
  • 在Linux上怎么清理垃圾系统管理员
    这篇文章主要介绍了在Linux上怎么清理垃圾系统管理员,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。rm 的那些事首先,这条命令是用来清除 Linux 系统的根目录(/)下所...
    99+
    2023-06-16
  • 在Ubuntu系统上怎么安装Kdump来处理系统崩溃问题
    这篇文章主要介绍“在Ubuntu系统上怎么安装Kdump来处理系统崩溃问题”,在日常操作中,相信很多人在在Ubuntu系统上怎么安装Kdump来处理系统崩溃问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”在...
    99+
    2023-06-13
  • 在Linux系统中使用GDB来调试C++程序的方法
    这篇文章主要讲解了“在Linux系统中使用GDB来调试C++程序的方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“在Linux系统中使用GDB来调试C++程序的方法”吧!安装GDB大多数的...
    99+
    2023-06-13
  • 在Linux系统上怎么用nmap扫描SSL漏洞
    这篇文章主要介绍“在Linux系统上怎么用nmap扫描SSL漏洞”,在日常操作中,相信很多人在在Linux系统上怎么用nmap扫描SSL漏洞问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”在Linux系统上怎么...
    99+
    2023-06-12
  • 怎么在Linux系统上安装MRTG来监控网络流量
    这篇文章主要讲解了“怎么在Linux系统上安装MRTG来监控网络流量”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么在Linux系统上安装MRTG来监控网络流量”吧!Multi Route...
    99+
    2023-06-12
  • Linux操作文件系统怎么调用
    本篇内容介绍了“Linux操作文件系统怎么调用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!需要引入的头文件:#inlcude<uni...
    99+
    2023-06-21
  • linux怎么调用系统内核函数
    在Linux中,可以通过系统调用来调用系统内核函数。系统调用是用户程序和内核之间的接口,用于请求内核执行特定操作。 在C语言中,可以...
    99+
    2023-10-24
    linux
  • 如何在Linux系统上使用NumPy库来加速Python代码?
    在当今的数据科学和机器学习领域,Python已成为最受欢迎的编程语言之一。然而,Python在执行大规模数据处理和计算密集型任务时,往往速度较慢。为了解决这个问题,NumPy库被设计出来,它可以加速Python代码的执行。在本篇文章中,我们...
    99+
    2023-09-30
    numy linux leetcode
  • 如何在Linux系统上使用PHP来实现动态加载?
    在Linux系统上,PHP是一种非常流行的编程语言,它可以用于开发Web应用程序和动态网站。其中,动态加载是一种非常有用的技术,它可以使网站更加灵活和高效。下面我们将详细介绍如何在Linux系统上使用PHP来实现动态加载。 动态加载是指在运...
    99+
    2023-11-04
    load linux linux
  • 在Linux系统上怎么安装LinApple
    这篇文章主要介绍“在Linux系统上怎么安装LinApple”,在日常操作中,相信很多人在在Linux系统上怎么安装LinApple问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”在Linux系统上怎么安装Li...
    99+
    2023-06-26
  • 怎么在Linux系统上升级OpenSSL
    这篇文章主要讲解了“怎么在Linux系统上升级OpenSSL”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么在Linux系统上升级OpenSSL”吧!我是用的Centos ,目前官方说受威...
    99+
    2023-06-13
  • 怎么在Linux系统上搭建GitLab
    这篇文章主要介绍“怎么在Linux系统上搭建GitLab”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么在Linux系统上搭建GitLab”文章能帮助大家解决问题。环境准备操作系统:CentOS ...
    99+
    2023-07-05
  • 如何在Linux系统中使用Git来管理PHP项目?
    在软件开发中,版本控制是非常重要的一步。Git是一个流行的版本控制工具,可用于管理代码库和跟踪代码更改。在本文中,我们将探讨如何在Linux系统中使用Git来管理PHP项目。 安装Git 首先,您需要在Linux系统上安装Git。在大多数...
    99+
    2023-09-01
    path linux git
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作