日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

前段時(shí)間線上的一個(gè)使用 google Puppeteer 生成圖片的服務(wù)炸了,每個(gè) Docker 容器內(nèi)都有幾千個(gè)孤兒僵死進(jìn)程沒有回收,如下圖所示。

一次 Docker 容器內(nèi)大量僵尸進(jìn)程排查分析

 

這篇文章比較長,主要就講了下面這幾個(gè)問題。

  • 什么情況下會出現(xiàn)僵尸進(jìn)程、孤兒進(jìn)程
  • Puppeteer 工作過程啟動(dòng)的進(jìn)程與線上事故分析
  • PID 為 1 的進(jìn)程有什么特殊的地方
  • 為什么 node/npm 不應(yīng)該作為鏡像中 PID 為 1 的進(jìn)程
  • 為什么 Bash 可以作為 PID 為 1 的進(jìn)程,以及它做 PID 為 1 的進(jìn)程有什么缺陷
  • 鏡像中比較推薦的 init 進(jìn)程的做法是什么

Puppeteer 是一個(gè) node 庫,是 Chrome 官方提供的無界面 chrome 工具(headless chrome),它提供了操作 Chrome API 的方式,允許開發(fā)者在程序中啟動(dòng) chrome 進(jìn)程,調(diào)用 JS 的 API 實(shí)現(xiàn)頁面加載、數(shù)據(jù)爬取、web 自動(dòng)化測試等功能。

本案例中使用的場景是使用 Puppeteer 加載 html,隨后截圖生成一張分銷海報(bào)的圖片。文章分析了這個(gè)問題背后的原因,接下來開始正式的內(nèi)容。

進(jìn)程

每個(gè)進(jìn)程都有一個(gè)唯一的標(biāo)識,稱為 pid,pid 是一個(gè)非負(fù)的整數(shù)值,使用 ps 命令可以查看,在我的 mac 電腦上執(zhí)行 ps -ef 可以看到當(dāng)前運(yùn)行的所有進(jìn)程,如下所示。

UID   PID  PPID   C STIME   TTY           TIME CMD  0     1     0   0 六04下午 ??        23:09.18 /sbin/launchd  0    39     1   0 六04下午 ??         0:49.66 /usr/sbin/syslogd  0    40     1   0 六04下午 ??         0:13.00 /usr/libexec/UserEventAgent (System)

其中 PID 是表示進(jìn)程號。

系統(tǒng)中每個(gè)進(jìn)程都有對應(yīng)的父進(jìn)程,上面 ps 輸出中的 PPID 就表示進(jìn)程的父進(jìn)程號。最頂層的進(jìn)程的 PID 為 1,PPID 為 0。

打開 iTerm,在終端中執(zhí)行一個(gè)命令,比如 "ls",實(shí)際上系統(tǒng)會創(chuàng)建新的 iTerm 子進(jìn)程,這個(gè) iTerm 進(jìn)程又創(chuàng)建了 zsh 子進(jìn)程。在 zsh 中輸入的 ls 命令,則是 zsh 進(jìn)程又啟動(dòng)了一個(gè) ls 子進(jìn)程。在 iTerm 中輸入 ls 命令過程的進(jìn)程關(guān)系如下所示。

  UID   PID  PPID   C STIME   TTY           TIME CMD  501   321     1   0 六04下午 ??        61:01.45 /Applications/iTerm.app/Contents/MacOS/iTerm2 -psn_0_81940  501 97920   321   0  8:02上午 ttys039    0:00.07 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp arthur    0 97921 97920   0  8:02上午 ttys039    0:00.03 login -fp arthur  501 97922 97921   0  8:02上午 ttys039    0:00.29 -zsh  501 98369 97922   0  8:14上午 ttys039    0:00.00 ./a.out

進(jìn)程與 fork

前面提到的父進(jìn)程“創(chuàng)建”子進(jìn)程,更嚴(yán)謹(jǐn)?shù)拿枋鍪?fork(孵化、衍生)。下面來看一個(gè)實(shí)際的例子,新建一個(gè) fork_demo.c 文件。

#include <unistd.h>#include <stdio.h>int main() {  int ret = fork();  if (ret) {    printf("enter if blockn");  } else {    printf("enter else blockn");  }  return 0;}

執(zhí)行上的代碼,會輸出如下的語句。

enter if blockenter else block

可以看到 if、else 語句都被執(zhí)行了。

fork 調(diào)用

fork 是一個(gè)系統(tǒng)調(diào)用,它的方法聲明如下所示。

pid_t fork(void);

fork 調(diào)用完成后會生成一個(gè)新的子進(jìn)程,且父子進(jìn)程都從 fork 返回處繼續(xù)執(zhí)行。這里需要特別注意的是 fork 的返回值的含義,在父進(jìn)程和新的子進(jìn)程中,它們的含義不一樣。

  • 在父進(jìn)程中 fork 的返回值是新創(chuàng)建的子進(jìn)程 id
  • 在創(chuàng)建的子進(jìn)程中 fork 的返回值始終等于 0

因此可以通過 fork 的返回值區(qū)分父子進(jìn)程,在運(yùn)行過程中可以使用 getpid 方法獲取當(dāng)前的進(jìn)程 id。fork 典型的使用方式如下所示。

#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main() {  printf("before fork, pid=%dn", getpid());  pid_t childPid;  switch (childPid = fork()) {    case -1: {      // fork 失敗      printf("fork error, %dn", getpid());      exit(1);    }    case 0: {      // 子進(jìn)程代碼進(jìn)入到這里      printf("in child process, pid=%dn", getpid());      break;    }    default: {      // 父進(jìn)程代碼進(jìn)入到這里      printf("in parent process, pid=%d, child pid=%dn", getpid(), childPid);      break;    }  }  return 0;}

執(zhí)行上面的代碼,輸出結(jié)果如下所示。

before fork, pid=26070in parent process, pid=26070, child pid=26071in child process, pid=26071

子進(jìn)程是父進(jìn)程的副本,子進(jìn)程擁有父進(jìn)程數(shù)據(jù)空間、堆、棧的復(fù)制副本 ,fork 采用了 copy-on-write 技術(shù),fork 操作幾乎瞬間可以完成。只有在子進(jìn)程修改了相應(yīng)的區(qū)域才會進(jìn)行真正的拷貝。

孤兒進(jìn)程:不能同年同月同日生,也不會同年同月同日死

接下來問一個(gè)問題,父進(jìn)程掛掉時(shí),子進(jìn)程會掛掉嗎?

想象現(xiàn)實(shí)中的場景,父親不在了,兒子還可以活嗎?答案是肯定的。對應(yīng)于進(jìn)程,父進(jìn)程退出時(shí),子進(jìn)程會繼續(xù)運(yùn)行,不會一起共赴黃泉。

一個(gè)父進(jìn)程已經(jīng)終止的進(jìn)程被稱為孤兒進(jìn)程(orphan process)。操作系統(tǒng)這個(gè)大家長是比較人性化的,沒有人管的孤兒進(jìn)程會被進(jìn)程 ID 為 1 的進(jìn)程接管。這個(gè) PID 為 1 的進(jìn)程后面還會再講到。

接下來對之前的代碼稍作修改,讓父進(jìn)程 fork 子進(jìn)程以后自殺退出,生成孤兒進(jìn)程。代碼如下所示。

#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main() {  printf("before fork, pid=%dn", getpid());  pid_t childPid;  switch (childPid = fork()) {    case -1: {      printf("fork error, %dn", getpid());      exit(1);    }    case 0: {      printf("in child process, pid=%dn", getpid());      sleep(100000); // 子進(jìn)程 sleep 不退出      break;    }    default: {      printf("in parent process, pid=%d, child pid=%dn", getpid(), childPid);      exit(0); // 父進(jìn)程退出    }  }  return 0;}

編譯運(yùn)行上面的代碼

gcc fork_demo.c -o fork_demo; ./fork_demo

輸出結(jié)果如下。

before fork, pid=21629in parent process, pid=21629, child pid=21630in child process, pid=21630

可以看到父進(jìn)程 id 為 21629, 生成的子進(jìn)程 id 為 21630。

使用 ps 查看當(dāng)前進(jìn)程信息,結(jié)果如下所示。

UID        PID  PPID  C STIME TTY          TIME CMDroot         1     0  0 12月12 ?      00:00:53 /usr/lib/systemd/systemd --system --deserialize 21ya       21630     1  0 19:26 pts/8    00:00:00 ./fork_demo

可以看到此時(shí)孤兒子進(jìn)程 21630 的父 ID 已經(jīng)變?yōu)榱隧攲拥?ID 為 1 的進(jìn)程。

僵尸進(jìn)程

父進(jìn)程負(fù)責(zé)生,如果不負(fù)責(zé)養(yǎng),那就不是一個(gè)好父親。子進(jìn)程掛了,如果父進(jìn)程不給子進(jìn)程“收尸”(調(diào)用 wait/waitpid),那這個(gè)子進(jìn)程小可憐就變成了僵尸進(jìn)程。

新建一個(gè) make_zombie.c 文件,內(nèi)容如下。

#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main() {  printf("pid %dn", getpid());  int child_pid = fork();  if (child_pid == 0) {    printf("-----in child process:  %dn", getpid());    exit(0);  } else {    sleep(1000000);  }  return 0;}

編譯運(yùn)行上面的代碼,就可以生成一個(gè)進(jìn)程號為 22538 的僵尸進(jìn)程,如下所示。

UID        PID  PPID  C STIME TTY          TIME CMDya       22537 20759  0 19:57 pts/8    00:00:00 ./make_zombieya       22538 22537  0 19:57 pts/8    00:00:00 [make_zombie] <defunct>

CMD 名中的 defunct 表示這是一個(gè)僵尸進(jìn)程。

也使用 ps 命令查看進(jìn)程的狀態(tài),顯示為 "Z" 或者 "Z+" 表示這是一個(gè)僵尸進(jìn)程,如下所示。

ps -ho pid,state -p 2253822538 Z

子進(jìn)程退出后絕大部分資源已經(jīng)被釋放可供其他進(jìn)使用,但是內(nèi)核的進(jìn)程表中的槽位沒有釋放。

僵尸進(jìn)程有一個(gè)很神奇的特性,使用 kill -9 必殺信號都沒有辦法殺掉僵尸進(jìn)程,這樣的設(shè)計(jì)利弊參半,好的地方是父進(jìn)程可以總是有機(jī)會執(zhí)行 wait/waitpid 等命令收割子進(jìn)程,壞的地方是無法強(qiáng)制回收這種僵尸進(jìn)程。

PID 為 1 的進(jìn)程

linux 中內(nèi)核初始化以后會啟動(dòng)系統(tǒng)的第一個(gè)進(jìn)程,PID 為 1,也可以稱之為 init 進(jìn)程或者根(ROOT)進(jìn)程。在我的 centos 機(jī)器上,這個(gè) init 進(jìn)程是 systemd,如下所示。

UID        PID  PPID  C STIME TTY          TIME CMDroot         1     0  0 12月12 ?      00:00:54 /usr/lib/systemd/systemd --system --deserialize 21

在我的 Mac 電腦上,這個(gè)進(jìn)程為 launchd,如下所示。

UID   PID  PPID   C STIME   TTY           TIME CMD  0     1     0   0 六04下午 ??        28:40.65 /sbin/launchd

init 進(jìn)程有下面這幾個(gè)功能

  • 如果一個(gè)進(jìn)程的父進(jìn)程退出了,那么這個(gè) init 進(jìn)程便會接管這個(gè)孤兒進(jìn)程。
  • 如果一個(gè)進(jìn)程的父進(jìn)程未執(zhí)行 wait/waitpid 就退出了,init 進(jìn)程會接管子進(jìn)程并自動(dòng)調(diào)用 wait 方法,從而保證系統(tǒng)中的僵尸進(jìn)程可以被移除。
  • 傳遞信號給子進(jìn)程,這點(diǎn)后面會介紹。

為什么 Node.js 不適合做 Docker 鏡像中 PID 為 1 的進(jìn)程

在 Node.js 的官方最佳實(shí)踐里有寫到 "Node.js was not designed to run as PID 1 which leads to unexpected behaviour when running inside of Docker."。下圖來自 github.com/nodejs/dock… 。

一次 Docker 容器內(nèi)大量僵尸進(jìn)程排查分析

 

接下來會做兩個(gè)實(shí)驗(yàn):第一個(gè)實(shí)驗(yàn)是在 Centos 機(jī)器上,第二個(gè)實(shí)驗(yàn)是在 Docker 鏡像中

實(shí)驗(yàn)一:在 Centos 上,systemd 作為 PID 為 1 的進(jìn)程

下面來做一些測試,修改上面的代碼,將父進(jìn)程 sleep 的時(shí)間改短為 15s,新建一個(gè) make_zombie.c 文件,如下所示。

#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main() {  printf("pid %dn", getpid());  int child_pid = fork();  if (child_pid == 0) {    printf("-----in child process:  %dn", getpid());    exit(0);  } else {    sleep(15);    exit(0);  }}

編譯生成可執(zhí)行文件 make_zombie。

gcc make_zombie.c -o make_zombie

然后新建一個(gè) run.js 代碼,內(nèi)部啟動(dòng)一個(gè)進(jìn)程運(yùn)行 make_zombie,如下所示。

const { spawn } = require('child_process');const cmd = spawn('./make_zombie');cmd.stdout.on('data', (data) => {    console.log(`stdout: ${data}`);});cmd.stderr.on('data', (data) => {    console.error(`stderr: ${data}`);});cmd.on('close', (code) => {    console.log(`child process exited with code ${code}`);});setTimeout(function () {    console.log("...");}, 1000000);

執(zhí)行 node run.js 運(yùn)行這段 js 代碼,使用 ps -ef 查看進(jìn)程關(guān)系如下。

UID        PID  PPID  C STIME TTY          TIME CMDya       19234 19231  0 12月20 ?       00:00:00 sshd: ya@pts/6ya       19235 19234  0 12月20 pts/6   00:00:01 -zshya       29513 19235  3 15:28 pts/6    00:00:00 node run.jsya       29519 29513  0 15:28 pts/6    00:00:00 ./make_zombieya       29520 29519  0 15:28 pts/6    00:00:00 [make_zombie] <defunct>復(fù)制代碼

過 15s 以后,再次執(zhí)行 ps -ef 查詢當(dāng)前運(yùn)行的進(jìn)程,可以看到 make_zombie 相關(guān)進(jìn)程都不見了。

UID        PID  PPID  C STIME TTY          TIME CMDya       19234 19231  0 12月20 ?       00:00:00 sshd: ya@pts/6ya       19235 19234  0 12月20 pts/6   00:00:01 -zshya       29513 19235  3 15:28 pts/6    00:00:00 node run.js

這是因?yàn)?PID 為 29519 的 make_zombie 父進(jìn)程在 15s 以后退出,僵尸子進(jìn)程被托管到 init 進(jìn)程,這個(gè)進(jìn)程會調(diào)用 wait/waitfor 為這個(gè)僵尸收尸。

實(shí)驗(yàn)二:在 Docker 上,node 作為 PID 為 1 的進(jìn)程

將 make_zombie 可執(zhí)行文件和 run.js 打包為 .tar.gz 包,隨后新建一個(gè) Dockerfile,內(nèi)容如下。

#指定基礎(chǔ)鏡像FROM  registry.gz.cctv.cn/library/your_node_image:your_tagWORKDIR /#復(fù)制包文件到工作目錄,. 代表當(dāng)前目錄,也就是工作目錄ADD test.tar.gz .#指定啟動(dòng)命令CMD ["node", "run.js"]

執(zhí)行 docker build 命令構(gòu)建一個(gè)鏡像,在我的電腦上 Image ID 為 ab71925b5154, 執(zhí)行 docker run ab71925b5154,啟動(dòng) docker 鏡像,使用 docker ps 找到鏡像 CONTAINER ID,這里為 e37f7e3c2e39。隨即使用 docker exec 進(jìn)入到鏡像終端

docker exec -it e37f7e3c2e39 /bin/bash 

執(zhí)行 ps 命令查看當(dāng)前的進(jìn)程狀況,如下所示。

UID        PID  PPID  C STIME TTY          TIME CMDroot         1     0  1 07:52 ?        00:00:00 node run.jsroot        12     1  0 07:52 ?        00:00:00 ./make_zombieroot        13    12  0 07:52 ?        00:00:00 [make_zombie] <defunct>

等一段時(shí)間(15s),再次執(zhí)行 ps 查看當(dāng)前進(jìn)程,如下所示。

UID        PID  PPID  C STIME TTY          TIME CMDroot         1     0  0 07:52 ?        00:00:00 node run.jsroot        13     1  0 07:52 ?        00:00:00 [make_zombie] <defunct>

可以看到 PID 為 13 的僵尸進(jìn)程已經(jīng)托管到 PID 為 1 的 node 進(jìn)程,但是沒有被回收。

這是 node 不適合做 init 進(jìn)程的最主要原因:無法回收僵尸進(jìn)程。

說到 node,這里提一下 npm,npm 實(shí)際上是使用 npm 進(jìn)程啟動(dòng)了一個(gè)子進(jìn)程啟動(dòng)了 package.json 中 scripts 里寫的啟動(dòng)腳本,示例 package.json 腳本如下所示。

{  "name": "test-demo",  "version": "1.0.0",  "description": "",  "main": "index.js",  "scripts": {    "test": "echo "Error: no test specified" && exit 1",    "start": "node run.js"  },  "keywords": [],  "author": "",  "license": "ISC",  "dependencies": {  }}

使用 npm run start 啟動(dòng),得到的進(jìn)程如下所示。

ya       19235 19234  0 12月20 pts/6  00:00:01 -zshya       32252 19235  0 16:32 pts/6    00:00:00 npmya       32262 32252  0 16:32 pts/6    00:00:00 node run.js

與 node 一樣,npm 也不會處理僵尸子進(jìn)程回收。

線上問題分析

我們線上出問題的情況下使用 npm start 來啟動(dòng)一個(gè) Puppeteer 項(xiàng)目,每生成一次圖片便會創(chuàng)建 4 個(gè) chrome 相關(guān)的進(jìn)程,如下所示。

.|└── chrome(1)    ├── gpu-process(2)    └── zygote(3)        └── renderer(4)

在圖片生成完成時(shí),chrome 主進(jìn)程退出,剩下的三個(gè)孤兒僵尸進(jìn)程被托管到頂層 npm 進(jìn)程下,但是 npm 進(jìn)程無力回收,所有每生成一次圖片便會新增三個(gè)僵尸進(jìn)程。在成千上萬次圖片生成以后,系統(tǒng)中就充滿了僵尸進(jìn)程。

解決辦法

為了解決這個(gè)問題,不能讓 node/npm 成為 init 進(jìn)程,讓有能力接管僵尸進(jìn)程的服務(wù)成為 init 進(jìn)程即可,有兩個(gè)解決辦法。

  • 使用 bash 啟動(dòng) node 或者 npm
  • 增加專門的 init 進(jìn)程,比如 tini

解決方式一:使用 bash 啟動(dòng) node

讓 bash 成為頂層進(jìn)程是比較快的一種方式,bash 進(jìn)程會負(fù)責(zé)回收僵尸進(jìn)程,修改 Dockerfile,如下所示。

ADD test.tar.gz .# CMD ["npm", "run", "start"]CMD ["/bin/bash", "-c", "set -e && npm run start"]

使用這種方式是比較簡單,而且之前線上沒有出問題正是因?yàn)橐婚_始是使用這種 bash 方式啟動(dòng) node,后面有一個(gè)小兄弟為了統(tǒng)一啟動(dòng)命令將這個(gè)命令改為 npm run start,問題才出現(xiàn)的。

但使用 bash 并非完美的方案,它有一個(gè)比較嚴(yán)重的問題,bash 不會傳遞信號給它啟動(dòng)的進(jìn)程,優(yōu)雅停機(jī)等功能無法實(shí)現(xiàn)。

接下來做一個(gè)實(shí)驗(yàn),驗(yàn)證 bash 不會傳遞信號給子進(jìn)程的說法,新建一個(gè) signal_test.c 文件,它處理 SIGQUIT、SIGTERM、SIGTERM 三個(gè)信號,內(nèi)容如下。

#include <signal.h>#include <stdio.h>static void signal_handler(int signal_no) {  if (signal_no == SIGQUIT) {    printf("quit signal receive: %dn", signal_no);  } else if (signal_no == SIGTERM) {    printf("term signal receive: %dn", signal_no);  } else if (signal_no == SIGTERM) {    printf("interrupt signal receive: %dn", signal_no);  }}int main() {  printf("in mainn");  signal(SIGQUIT, signal_handler);  signal(SIGINT, signal_handler);  signal(SIGTERM, signal_handler);  getchar();}

在我 Centos 和 Mac 上運(yùn)行這個(gè) signal_test 程序時(shí),發(fā)送 kill -2、-3、-15 給這個(gè)程序,都會有對應(yīng)的打印輸出,表示收到了信號。如下所示。

kill -15 47120term signal receive: 15kill -3 47120quit signal receive: 3kill -2 47120interrupt signal receive: 2

在 Docker 鏡像中使用 bash 啟動(dòng)這個(gè)程序時(shí),發(fā)送 kill 命令給 bash 以后,bash 并不會將信號傳遞給 signal_test 程序。在執(zhí)行 docker stop 以后,docker 會發(fā)送 SIGTERM(15) 信號給 bash,bash 并不會將這個(gè)信號傳遞給啟動(dòng)的應(yīng)用程序,只能等一段時(shí)間超時(shí),docker 會發(fā)送 kill -9 強(qiáng)制殺死這個(gè) docker 進(jìn)程,無法達(dá)到優(yōu)雅停機(jī)的功能。

于是有了下面的第二種解決方案。

解決方式二:使用專門的 init 進(jìn)程

Node.js 提供了兩種方案,第一種是使用 docker 官方的輕量級 init 系統(tǒng),如下所示。

docker run -it --init you_docker_image_id

這種啟動(dòng)方式會以 /sbin/docker-init 為 PID 為 1 的 init 進(jìn)程,不會把 Dockerfile 中 CMD 作為第一個(gè)啟動(dòng)進(jìn)程。

以下面的 Dockerfile 內(nèi)容為例

...CMD ["./signal_test"]...

執(zhí)行 docker run -it --init image_id 啟動(dòng) docker 鏡像,此時(shí)鏡像內(nèi)的進(jìn)程如下所示。

UID        PID  PPID  C STIME TTY          TIME CMDroot         1     0  0 15:30 pts/0    00:00:00 /sbin/docker-init -- /app/node-defaultroot         6     1  0 15:30 pts/0    00:00:00 ./signal_test

可以看到 signal_test 程序作為 docker-init 的子進(jìn)程啟動(dòng)了。

在 docker stop 命令發(fā)送 SIGTERM 信號給鏡像以后,docker-init 進(jìn)程會將這個(gè)信號轉(zhuǎn)給 signal_test,這個(gè)應(yīng)用進(jìn)程就可以收到 SIGTERM 信號做自定義的處理,比如優(yōu)雅停機(jī)等。

除了 docker 的官方方案,Node.js 的最佳實(shí)踐還推薦了一個(gè) tini 這樣一個(gè) C 語言寫的極小的 init 進(jìn)程,github.com/krallin/tin… 。它的代碼較短,很值得一讀,對理解信號傳遞、處理僵尸進(jìn)程非常有幫助。

小結(jié)

通過這篇文章,希望你可以搞懂僵尸進(jìn)程、孤兒進(jìn)程、PID 為 1 的進(jìn)程是什么,以及為什么 node/npm 不適合做 PID 為 1 的進(jìn)程,bash 作為 PID 為 1 的進(jìn)程有什么缺陷。

下面留一個(gè)作業(yè)題,考考你對進(jìn)程 fork 函數(shù)的理解。如下程序連續(xù)調(diào)用三次 fork() 調(diào)用后會產(chǎn)生多少新進(jìn)程?

#include <stdio.h>#include <unistd.h>int main() {  printf("Hello, World!n");  fork();  fork();  fork();  sleep(100);  return 0;}

分享到:
標(biāo)簽:進(jìn)程 Docker
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定