返回顶部
首页 > 资讯 > 操作系统 >使用Linux Strace跟踪调试Oracle程序进程
  • 533
分享到

使用Linux Strace跟踪调试Oracle程序进程

2024-04-02 19:04:59 533人浏览 八月长安
摘要

  所谓操作系统,是应用程序与服务器硬件进行沟通的中间层。应用程序的所有操作,都是和操作系统进行沟通交互。操作系统负责将所有交互转化为设备语言,进行硬件交互。 我们在进行orac

 

所谓操作系统,是应用程序与服务器硬件进行沟通的中间层。应用程序的所有操作,都是和操作系统进行沟通交互。操作系统负责将所有交互转化为设备语言,进行硬件交互。

我们在进行oracle故障调试和内核原理工作的时候,经常需要了解后台运行的动作和细节。一些故障场景,如程序进程hang住、无法登陆等问题,就需要操作系统级别监控,检查定位问题。

Oracle自身已经提供了很多这类型的工具,如oradebug、各种等待事件和跟踪方式。此外,各类型的操作系统提供出很多系统级别工具,帮助我们进行监控。本篇主要介绍linux环境中的strace工具典型使用方法,留待需要朋友待查。

 

1、环境介绍

 

笔者使用红帽Red Hat 6.5进行测试

 

 

[root@XXX-Standby-Asm ~]# cat /etc/redhat-release

Red Hat Enterprise Linux Server release 6.5 (SantiaGo)

[root@XXX-Standby-Asm ~]# uname -a

Linux XXX-Standby-Asm 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux

 

 

对应使用Oracle版本为11.2.0.4。

 

 

[oracle@XXX-Standby-Asm ~]$ sqlplus /nolog

 

SQL*Plus: Release 11.2.0.4.0 Production on Tue Jun 16 16:39:21 2015

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

 

SQL> conn / as sysdba

Connected.

SQL> select * from v$version;

 

BANNER

--------------------------------------------------------------------------------

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

PL/SQL Release 11.2.0.4.0 - Production

CORE    11.2.0.4.0      Production

TNS for Linux: Version 11.2.0.4.0 - Production

NLSRTL Version 11.2.0.4.0 – Production

 

 

2Strace命令信息

 

使用-h参数,可以调用出strace命令的语法格式和各个使用参数。

 

 

[oracle@XXX-Standby-Asm ~]$ strace -h

usage: strace [-dDffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]

              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...

              [command [arg ...]]

   or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...

              [command [arg ...]]

-c -- count time, calls, and errors for each syscall and report summary

-f -- follow forks, -ff -- with output into separate files

-F -- attempt to follow vforks, -h -- print help message

-i -- print instruction pointer at time of syscall

-q -- suppress messages about attaching, detaching, etc.

-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs

-T -- print time spent in each syscall, -V -- print version

-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args

-x -- print non-ascii strings in hex, -xx -- print all strings in hex

-a column -- alignment COLUMN for printing syscall results (default 40)

-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...

   options: trace, abbrev, verbose, raw, signal, read, or write

-o file -- send trace output to FILE instead of stderr

-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs

-p pid -- trace process with process id PID, may be repeated

-D -- run tracer process as a detached grandchild, not as parent

-s strsize -- limit length of print strings to STRSIZE chars (default 32)

-S sortby -- sort syscall counts by: time, calls, name, nothing (default time)

-u username -- run command as username handling setuid and/or setgid

-E var=val -- put var=val in the environment for command

-E var -- remove var from the environment for command

 

 

在诸多参数中,比较常用的有如下几个:

 

ü  -t参数:可以显示调用操作系统过程的时间。这个在诊断中很重要,如果发现某一个执行过程时间消耗大,就可以定位到是什么问题;

ü  -p参数:strace除了可以从进程启动时候开始监控之外,还可以根据操作系统进程编号,进入一个运行中的进程进行debug;

ü  -o参数:输出结果如果需要以文件方式保存,就通过-o参数指定文件名称;

ü  -e参数:监控表达式。提供trace、signal、read和write等内容,反映监控方面项目。常用的参数是trace=file,集中在操作系统文件访问层面。

 

下面,通过两个典型应用场景,来演示一下strace应用。

 

3、启动程序监控

 

strace监控研究的一个重要范例是sqlplus,很多前辈使用这个工具来测试跟踪sqlplus启动过程访问的文件形式。启动strace监控sqlplus,就是在strace命令后直接输入sqlplus命令即可。

 

 

--启动命令

[oracle@localhost ~]$ strace -t -e trace=file sqlplus /nolog

14:21:14 execve("/u01/app/oracle/bin/sqlplus", ["sqlplus", "/nolog"], []) = 0 –启动命令

14:21:14 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)

14:21:14 open("/u01/app/oracle/lib/tls/x86_64/libsqlplus.so", O_RDONLY) = -1 ENOENT (No such file or directory)

14:21:14 stat("/u01/app/oracle/lib/tls/x86_64", 0x7fff3076da50) = -1 ENOENT (No such file or directory)

14:21:14 open("/u01/app/oracle/lib/tls/libsqlplus.so", O_RDONLY) = -1 ENOENT (No such file or directory)

14:21:14 stat("/u01/app/oracle/lib/tls", 0x7fff3076da50) = -1 ENOENT (No such file or directory)

14:21:14 open("/u01/app/oracle/lib/x86_64/libsqlplus.so", O_RDONLY) = -1 ENOENT (No such file or directory)

14:21:14 stat("/u01/app/oracle/lib/x86_64", 0x7fff3076da50) = -1 ENOENT (No such file or directory)

14:21:14 open("/u01/app/oracle/lib/libsqlplus.so", O_RDONLY) = 3

14:21:14 open("/u01/app/oracle/lib/libclntsh.so.11.1", O_RDONLY) = 3

14:21:14 open("/u01/app/oracle/lib/libnnz11.so", O_RDONLY) = 3

14:21:14 open("/u01/app/oracle/lib/libdl.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)

(篇幅原因,有省略……)

14:21:14 access("/etc/tnsnav.ora", F_OK) = -1 ENOENT (No such file or directory)

14:21:14 access("/u01/app/oracle/network/admin/tnsnav.ora", F_OK) = -1 ENOENT (No such file or directory)

14:21:14 open("/u01/app/oracle/oracore/zoneinfo", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 6

14:21:14 open("/u01/app/oracle/oracore/zoneinfo/timezlrg_1.dat", O_RDONLY) = 7

14:21:14 open("/u01/app/oracle/oracore/zoneinfo/timezlrg_2.dat", O_RDONLY) = 7

(读取各种时区数据……)

14:21:14 open("/u01/app/oracle/oracore/zoneinfo/timezone_14.dat", O_RDONLY) = 7

14:21:14 open("/u01/app/oracle/oracore/zoneinfo/timezlrg_14.dat", O_RDONLY) = 6

14:21:14 open("/usr/lib64/libnuma.so", O_RDONLY) = -1 ENOENT (No such file or directory)

14:21:14 open("/usr/lib64/libnuma.so.1", O_RDONLY) = 6

14:21:14 open("/proc/self/status", O_RDONLY) = 6

14:21:14 open("/sys/devices/system/node", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 6

14:21:14 open("/sys/devices/system/node/node0/meminfo", O_RDONLY) = 7

14:21:14 open("/sys/devices/system/cpu", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 6

14:21:14 open("/proc/self/status", O_RDONLY) = 6

14:21:14 open("/proc/sys/kernel/shmmax", O_RDONLY) = 6

14:21:14 open("/proc/meminfo", O_RDONLY) = 6

14:21:14 open("/usr/lib64/libnuma.so", O_RDONLY) = -1 ENOENT (No such file or directory)

14:21:14 open("/etc/localtime", O_RDONLY) = 6

14:21:14 open("/u01/app/oracle/rdbms/mesg/ocius.msb", O_RDONLY) = 6

 

SQL*Plus: Release 11.2.0.4.0 Production on Fri Jun 12 14:21:14 2015

 

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

 

--启动之后,读取的文件。

14:21:14 stat("login.sql", 0x7fff3076c740) = -1 ENOENT (No such file or directory)

14:21:14 stat("/u01/app/oracle/sqlplus/admin/glogin.sql", {st_mode=S_IFREG|0644, st_size=368, ...}) = 0

14:21:14 access("/u01/app/oracle/sqlplus/admin/glogin.sql", F_OK) = 0

14:21:14 statfs("/u01/app/oracle/sqlplus/admin/glogin.sql", {f_type="EXT2_SUPER_MAGIC", f_bsize=4096, f_blocks=174170552, f_bfree=147038320, f_bavail=138190973, f_files=44236800, f_ffree=44019067, f_fsid={1821877354, 763674030}, f_namelen=255, f_frsize=4096}) = 0

14:21:14 open("/u01/app/oracle/sqlplus/admin/glogin.sql", O_RDONLY) = 7

 

 

如果在启动sqlplus过程中,直接进行登录。跟踪过程中还包括了登录动作。

 

 

[oracle@localhost ~]$ strace -t -e trace=file sqlplus / as sysdba

14:29:30 execve("/u01/app/oracle/bin/sqlplus", ["sqlplus", "/", "as", "sysdba"], []) = 0

(相同篇幅内容,略……)

 

 

SQL*Plus: Release 11.2.0.4.0 Production on Fri Jun 12 14:29:30 2015

 

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

--差异部分

14:29:30 open("/u01/app/oracle/dbs/cm_xxxdb.dat", O_RDONLY|O_DSYNC) = -1 ENOENT (No such file or directory)

14:29:30 getcwd("/home/oracle", 256)    = 13

14:29:30 open("/proc/self/cmdline", O_RDONLY) = 7

14:29:30 open("/etc/nsswitch.conf", O_RDONLY) = 7

14:29:30 open("/u01/app/oracle/lib/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)

14:29:30 open("/etc/ld.so.cache", O_RDONLY) = 7

14:29:30 open("/lib64/libnss_files.so.2", O_RDONLY) = 7

14:29:30 open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 7

14:29:30 open("/u01/app/oracle/lib/libnque11.so", O_RDONLY) = 7

14:29:30 getcwd("/home/oracle", 256)    = 13

14:29:30 open("/u01/app/oracle/nls/data/lx20369.nlb", O_RDONLY) = 7

14:29:30 open("/u01/app/oracle/nls/data/lx207d0.nlb", O_RDONLY) = 7

14:29:30 readlink("/proc/self/fd/0", "/dev/pts/0", 254) = 10

14:29:30 open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 7

14:29:30 open("/etc/host.conf", O_RDONLY) = 7

14:29:30 open("/etc/resolv.conf", O_RDONLY) = 7

14:29:30 open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 7

14:29:30 open("/etc/hostid", O_RDONLY)  = -1 ENOENT (No such file or directory)

14:29:30 open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 7

14:29:30 open("/u01/app/oracle/rdbms/mesg/oraus.msb", O_RDONLY) = 7

 

Connected to:

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

 

14:29:30 stat("login.sql", 0x7fff0a822b10) = -1 ENOENT (No such file or directory)

14:29:30 stat("/u01/app/oracle/sqlplus/admin/glogin.sql", {st_mode=S_IFREG|0644, st_size=368, ...}) = 0

14:29:30 access("/u01/app/oracle/sqlplus/admin/glogin.sql", F_OK) = 0

14:29:30 statfs("/u01/app/oracle/sqlplus/admin/glogin.sql", {f_type="EXT2_SUPER_MAGIC", f_bsize=4096, f_blocks=174170552, f_bfree=147038317, f_bavail=138190970, f_files=44236800, f_ffree=44019066, f_fsid={1821877354, 763674030}, f_namelen=255, f_frsize=4096}) = 0

14:29:30 open("/u01/app/oracle/sqlplus/admin/glogin.sql", O_RDONLY) = 7

 

 

4、跟踪执行进程方式

 

除了上面介绍的方法外,strace还可以直接跟踪监控正在执行的系统进程。下面我们来观察一下strace对Oracle后台CKPT进程的监控。

 

 

[oracle@XXX-Standby-Asm ~]$ ps -ef | grep ckpt

grid     15950     1  0 Jun05 ?        00:01:02 asm_ckpt_+ASM

oracle   18608 17848  0 17:35 pts/0    00:00:00 grep ckpt

oracle   21395     1  0 Jun08 ?        00:04:27 ora_ckpt_xxxstb

 

 

从root角度,跟踪进程编号21395的后台进程。

 

 

[root@XXX-Standby-Asm ~]# strace -t -p 21395

Process 21395 attached - interrupt to quit

17:36:42 times({tms_utime=12512, tms_stime=14273, tms_cutime=0, tms_cstime=0}) = 645608271

17:36:42 semtimedop(6062085, {{16, -1, 0}}, 1, {1, 840000000}) = -1 EAGAIN (Resource temporarily unavailable)

17:36:44 getrusage(RUSAGE_SELF, {ru_utime={125, 122978}, ru_stime={142, 730301}, ...}) = 0

17:36:44 getrusage(RUSAGE_SELF, {ru_utime={125, 122978}, ru_stime={142, 730301}, ...}) = 0

17:36:44 times({tms_utime=12512, tms_stime=14273, tms_cutime=0, tms_cstime=0}) = 645608455

17:36:44 times({tms_utime=12512, tms_stime=14273, tms_cutime=0, tms_cstime=0}) = 645608455

17:36:44 read(16, "MSA\0\2\0\10\0P\0\0\0\0\0\0\0\20?P\r\0\0\0\0\0\200\330\266\177\177\0\0"..., 80) = 80

17:36:44 read(16, "MSA\0\2\0\10\0P\0\0\0\0\0\0\0\20?P\r\0\0\0\0\0\200\330\266\177\177\0\0"..., 80) = 80

17:36:44 times({tms_utime=12512, tms_stime=14273, tms_cutime=0, tms_cstime=0}) = 645608455

17:36:44 semtimedop(6062085, {{16, -1, 0}}, 1, {3, 0}) = -1 EAGAIN (Resource temporarily unavailable) –三秒差异

17:36:47 getrusage(RUSAGE_SELF, {ru_utime={125, 123978}, ru_stime={142, 731301}, ...}) = 0

17:36:47 getrusage(RUSAGE_SELF, {ru_utime={125, 123978}, ru_stime={142, 731301}, ...}) = 0

17:36:47 times({tms_utime=12512, tms_stime=14273, tms_cutime=0, tms_cstime=0}) = 645608755

17:36:47 times({tms_utime=12512, tms_stime=14273, tms_cutime=0, tms_cstime=0}) = 645608755

17:36:47 read(16, "MSA\0\2\0\10\0P\0\0\0\0\0\0\0\20?P\r\0\0\0\0\0\200\330\266\177\177\0\0"..., 80) = 80

17:36:47 read(16, "MSA\0\2\0\10\0P\0\0\0\0\0\0\0\20?P\r\0\0\0\0\0\200\330\266\177\177\0\0"..., 80) = 80

17:36:47 read(16, "MSA\0\2\0\10\0P\0\0\0\0\0\0\0\20?P\r\0\0\0\0\0\200\330\266\177\177\0\0"..., 80) = 80

17:36:47 read(16, "MSA\0\2\0\10\0P\0\0\0\0\0\0\0\20?P\r\0\0\0\0\0\200\330\266\177\177\0\0"..., 80) = 80

17:36:47 read(16, "MSA\0\2\0\10\0P\0\0\0\0\0\0\0\20?P\r\0\0\0\0\0\200\330\266\177\177\0\0"..., 80) = 80

17:36:47 read(16, "MSA\0\2\0\10\0P\0\0\0\0\0\0\0\20?P\r\0\0\0\0\0\200\330\266\177\177\0\0"..., 80) = 80

17:36:47 times({tms_utime=12512, tms_stime=14273, tms_cutime=0, tms_cstime=0}) = 645608756

17:36:47 times({tms_utime=12512, tms_stime=14273, tms_cutime=0, tms_cstime=0}) = 645608756

17:36:47 times({tms_utime=12512, tms_stime=14273, tms_cutime=0, tms_cstime=0}) = 645608756

17:36:47 times({tms_utime=12512, tms_stime=14273, tms_cutime=0, tms_cstime=0}) = 645608756

17:36:47 times({tms_utime=12512, tms_stime=14273, tms_cutime=0, tms_cstime=0}) = 645608756

17:36:47 semtimedop(6062085, {{16, -1, 0}}, 1, {3, 0}^C <unfinished ...>

Process 21395 detached

 

 

从里面,我们可以看到ckpt的动作方式。

 

5、结论

 

Strace是Linux环境下的一个非常有用的工具。用好这个工具,可以让我们更加接近内核细节,丰富知识能力。


--结束END--

本文标题: 使用Linux Strace跟踪调试Oracle程序进程

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

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

猜你喜欢
  • 使用Linux Strace跟踪调试Oracle程序进程
      所谓操作系统,是应用程序与服务器硬件进行沟通的中间层。应用程序的所有操作,都是和操作系统进行沟通交互。操作系统负责将所有交互转化为设备语言,进行硬件交互。 我们在进行Orac...
    99+
    2024-04-02
  • Linux中怎么跟踪系统启动时的进程顺序
    要跟踪系统启动时的进程顺序,可以使用以下方法: 查看启动日志文件:系统启动时会生成启动日志文件,可以查看该文件以了解系统启动时的...
    99+
    2024-04-02
  • 怎么使用eclipse进行程序调试
    使用Eclipse进行程序调试的步骤如下:1. 在Eclipse中打开要调试的Java项目,并确保项目已经编译成功。2. 在代码中设...
    99+
    2023-09-13
    eclipse
  • Linux如何使用gdb调试多进程
    这篇文章主要介绍了Linux如何使用gdb调试多进程的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Linux如何使用gdb调试多进程文章都会有所收获,下面我们一起来看看吧。一.gdb常用目录表操作描述l命令相当...
    99+
    2023-06-28
  • linux中怎么使用gdb调试程序
    在Linux中使用gdb调试程序,可以按照以下步骤进行操作:1. 在命令行中编译你的程序时,加上`-g`选项,以便生成调试信息。例如...
    99+
    2023-09-13
    linux
  • 使用pycharm远程调试程序&连接linux服务器调试程序(亲测可行!!)
    目录 方法1与方法2的前提:为远程python解释器创建部署配置 远程调试方法1: 使用远程python解释器 远程调试方法2: 使用python远程调试服务器设置进行远程调试 补充说明:可能遇到的问题。。 提示:请注意看我教程中的图片!...
    99+
    2023-09-05
    pycharm 服务器 ide
  • 在软件部署中如何使用strace进行调试
    这篇文章主要介绍在软件部署中如何使用strace进行调试,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!什么是 strace?strace 是一个用来“追踪系统调用”的工具。它主要是一个 Linux 工具,但是你也可以...
    99+
    2023-06-16
  • Linux应用程序使用写文件调试程序的方法
    linux,一切皆文件,那么在android系统本身,也是Linux+java罢了,也是在Linux的运行环境下。 通常,我们在调试程序的都会使用printf。 在Android中,我们会去使用logcat,现在,给大家...
    99+
    2022-06-04
    应用程序bug调试 写文件调试程序 linux应用程序使用写文件调试程序的方法
  • Linux程序调试工具gdb怎么使用
    这篇文章主要介绍“Linux程序调试工具gdb怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Linux程序调试工具gdb怎么使用”文章能帮助大家解决问题。gdb是GNU开源组织发布的一个强大...
    99+
    2023-06-27
  • Linux下怎么使用gdb调试go程序
    在golang的开发过程中,我们常常会遇到需要调试问题的情况。这时,我们需要工具来辅助我们进行调试。在golang中,最常用的调试工具就是gdb了。本文将介绍如何在Linux操作系统下安装和配置gdb。一、什么是gdb?gdb是一款可以在多...
    99+
    2023-05-14
  • C#中如何使用日志记录跟踪程序运行
    C#中如何使用日志记录跟踪程序运行,需要具体代码示例引言:在开发软件时,常常需要对程序运行情况进行跟踪和记录,以便在出现问题时能够准确找到问题所在。日志记录是一种重要的技术手段,可以记录程序的运行状态、错误信息和调试信息,以便进行异常定位和...
    99+
    2023-10-22
    跟踪 程序运行 C#: 日志记录
  • 在Linux中怎么使用gdb调试C程序
    这篇文章主要为大家展示了“在Linux中怎么使用gdb调试C程序”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“在Linux中怎么使用gdb调试C程序”这篇文章吧。无论多么有经验的程序员,开发的任...
    99+
    2023-06-16
  • Linux系统下如何使用GDB调试程序
    本文将为大家详细介绍“Linux系统下如何使用GDB调试程序”,内容步骤清晰详细,细节处理妥当,而小编每天都会更新不同的知识点,希望这篇“Linux系统下如何使用GDB调试程序”能够给你意想不到的收获,请大家跟着小编的思路慢慢深入,具体内容...
    99+
    2023-06-28
  • python使用IPython调试debug程序
    目录安装使用方法优点提示和不足参考链接关于IPython使用的入门文章,主要介绍了如何在程序代码中嵌入ipython用于调试,并分析了优点与不足。 在 Python 中编程时,我会花...
    99+
    2024-04-02
  • 怎么使用Flex调试程序
    这篇文章主要为大家展示了“怎么使用Flex调试程序”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“怎么使用Flex调试程序”这篇文章吧。使用Flex调试程序如果Flex程序编译时报错,需要修改程序...
    99+
    2023-06-17
  • C++ 函数调试详解:如何使用日志和跟踪功能?
    摘要:为了调试 c++++ 函数,可以使用日志和跟踪功能:日志记录:记录消息和错误,了解函数行为。可使用 std::cerr 流或日志库。跟踪:插入检查点,收集变量值和函数调用信息。可使...
    99+
    2024-05-03
    调试 c++
  • 用 ipdb 调试 Python 程序
    ==> 安装  pip install ipdb==> 使用    ---> python -m ipdb xxx.py  程序内部: from ipdb import set_trace set_trace()==>...
    99+
    2023-01-31
    程序 ipdb Python
  • Linux系统上怎么进行Go语言程序调试
    这篇文章主要讲解了“Linux系统上怎么进行Go语言程序调试”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Linux系统上怎么进行Go语言程序调试”吧!调试工具Go语言提供了内置的调试器——...
    99+
    2023-07-06
  • 如何使用PHP开发微信小程序的任务跟踪功能?
    如何使用PHP开发微信小程序的任务跟踪功能?随着微信小程序的普及和使用,越来越多的开发者开始将其应用于各种场景。其中,任务跟踪功能是许多应用场景中常见的需求之一。本文将介绍如何使用PHP开发微信小程序的任务跟踪功能,并提供具体的代码示例。在...
    99+
    2023-10-27
    微信小程序 PHP开发 任务跟踪功能
  • 如何进行小程序的测试与调试
    小程序的测试与调试可以通过以下几个步骤来进行: 使用开发者工具:小程序开发者工具是一个专门用于小程序开发和调试的工具,可以在其中...
    99+
    2024-04-17
    小程序
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作