mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-11-16 22:23:45 +08:00
u
This commit is contained in:
@@ -25,13 +25,7 @@
|
||||
<meta name="generator" content="Hexo 4.2.0">
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div class="book-container">
|
||||
|
||||
<div class="book-sidebar">
|
||||
@@ -55,385 +49,196 @@
|
||||
<li><a href="/" class="current-tab">首页</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<ul class="uncollapsible">
|
||||
|
||||
<li><a href="../">上一级</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<ul class="uncollapsible">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/00 开篇词 一个态度两个步骤,成为容器实战高手.md.html">00 开篇词 一个态度两个步骤,成为容器实战高手.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/01 认识容器:容器的基本操作和实现原理.md.html">01 认识容器:容器的基本操作和实现原理.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/02 理解进程(1):为什么我在容器中不能kill 1号进程?.md.html">02 理解进程(1):为什么我在容器中不能kill 1号进程?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/03 理解进程(2):为什么我的容器里有这么多僵尸进程?.md.html">03 理解进程(2):为什么我的容器里有这么多僵尸进程?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
<a class="current-tab" href="/专栏/容器实战高手课/04 理解进程(3):为什么我在容器中的进程被强制杀死了?.md.html">04 理解进程(3):为什么我在容器中的进程被强制杀死了?.md.html</a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/05 容器CPU(1):怎么限制容器的CPU使用?.md.html">05 容器CPU(1):怎么限制容器的CPU使用?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/06 容器CPU(2):如何正确地拿到容器CPU的开销?.md.html">06 容器CPU(2):如何正确地拿到容器CPU的开销?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/07 Load Average:加了CPU Cgroup限制,为什么我的容器还是很慢?.md.html">07 Load Average:加了CPU Cgroup限制,为什么我的容器还是很慢?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/08 容器内存:我的容器为什么被杀了?.md.html">08 容器内存:我的容器为什么被杀了?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/09 Page Cache:为什么我的容器内存使用量总是在临界点.md.html">09 Page Cache:为什么我的容器内存使用量总是在临界点.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/10 Swap:容器可以使用Swap空间吗?.md.html">10 Swap:容器可以使用Swap空间吗?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/11 容器文件系统:我在容器中读写文件怎么变慢了.md.html">11 容器文件系统:我在容器中读写文件怎么变慢了.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/12 容器文件Quota:容器为什么把宿主机的磁盘写满了?.md.html">12 容器文件Quota:容器为什么把宿主机的磁盘写满了?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/13 容器磁盘限速:我的容器里磁盘读写为什么不稳定.md.html">13 容器磁盘限速:我的容器里磁盘读写为什么不稳定.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/14 容器中的内存与IO:容器写文件的延时为什么波动很大?.md.html">14 容器中的内存与IO:容器写文件的延时为什么波动很大?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/15 容器网络:我修改了procsysnet下的参数,为什么在容器中不起效?.md.html">15 容器网络:我修改了procsysnet下的参数,为什么在容器中不起效?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/16 容器网络配置(1):容器网络不通了要怎么调试.md.html">16 容器网络配置(1):容器网络不通了要怎么调试.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/17 容器网络配置(2):容器网络延时要比宿主机上的高吗.md.html">17 容器网络配置(2):容器网络延时要比宿主机上的高吗.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/18 容器网络配置(3):容器中的网络乱序包怎么这么高?.md.html">18 容器网络配置(3):容器中的网络乱序包怎么这么高?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/19 容器安全(1):我的容器真的需要privileged权限吗.md.html">19 容器安全(1):我的容器真的需要privileged权限吗.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/20 容器安全(2):在容器中,我不以root用户来运行程序可以吗?.md.html">20 容器安全(2):在容器中,我不以root用户来运行程序可以吗?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/加餐01 案例分析:怎么解决海量IPVS规则带来的网络延时抖动问题?.md.html">加餐01 案例分析:怎么解决海量IPVS规则带来的网络延时抖动问题?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/加餐02 理解perf:怎么用perf聚焦热点函数?.md.html">加餐02 理解perf:怎么用perf聚焦热点函数?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/加餐03 理解ftrace(1):怎么应用ftrace查看长延时内核函数?.md.html">加餐03 理解ftrace(1):怎么应用ftrace查看长延时内核函数?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/加餐04 理解ftrace(2):怎么理解ftrace背后的技术tracepoint和kprobe?.md.html">加餐04 理解ftrace(2):怎么理解ftrace背后的技术tracepoint和kprobe?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/加餐05 eBPF:怎么更加深入地查看内核中的函数?.md.html">加餐05 eBPF:怎么更加深入地查看内核中的函数?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/加餐06 BCC:入门eBPF的前端工具.md.html">加餐06 BCC:入门eBPF的前端工具.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/加餐福利 课后思考题答案合集.md.html">加餐福利 课后思考题答案合集.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/容器实战高手课/结束语 跳出舒适区,突破思考的惰性.md.html">结束语 跳出舒适区,突破思考的惰性.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||||
|
||||
<div class="sidebar-toggle-inner"></div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
function add_inner() {
|
||||
@@ -443,9 +248,6 @@
|
||||
inner.classList.add('show')
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function remove_inner() {
|
||||
|
||||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||||
@@ -453,9 +255,6 @@
|
||||
inner.classList.remove('show')
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function sidebar_toggle() {
|
||||
|
||||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||||
@@ -485,9 +284,6 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function open_sidebar() {
|
||||
|
||||
let sidebar = document.querySelector('.book-sidebar')
|
||||
@@ -511,13 +307,7 @@ function hide_canvas() {
|
||||
overlay.classList.remove('show')
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<div class="off-canvas-content">
|
||||
|
||||
<div class="columns">
|
||||
@@ -585,9 +375,6 @@ function hide_canvas() {
|
||||
<pre><code>
|
||||
|
||||
docker run -d --name fwd_sig registry/fwd_sig:v1 /c-init-sig
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>你会发现,在我们用 docker stop 停止这个容器的时候,如果用 strace 工具来监控,就能看到容器里的 init 进程和另外一个进程收到的信号情况。</p>
|
||||
@@ -599,9 +386,6 @@ docker run -d --name fwd_sig registry/fwd_sig:v1 /c-init-sig
|
||||
<pre><code>
|
||||
|
||||
# ps -ef | grep c-init-sig
|
||||
|
||||
|
||||
|
||||
root 15857 14391 0 06:23 pts/0 00:00:00 docker run -it registry/fwd_sig:v1 /c-init-sig
|
||||
|
||||
root 15909 15879 0 06:23 pts/0 00:00:00 /c-init-sig
|
||||
@@ -609,13 +393,7 @@ root 15909 15879 0 06:23 pts/0 00:00:00 /c-init-sig
|
||||
root 15959 15909 0 06:23 pts/0 00:00:00 /c-init-sig
|
||||
|
||||
root 16046 14607 0 06:23 pts/3 00:00:00 grep --color=auto c-init-sig
|
||||
|
||||
|
||||
|
||||
# strace -p 15909
|
||||
|
||||
|
||||
|
||||
strace: Process 15909 attached
|
||||
|
||||
restart_syscall(<... resuming interrupted read ...>) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
|
||||
@@ -627,9 +405,6 @@ write(1, "received SIGTERM\n", 17) = 17
|
||||
exit_group(0) = ?
|
||||
|
||||
+++ exited with 0 +++
|
||||
|
||||
|
||||
|
||||
# strace -p 15959
|
||||
|
||||
strace: Process 15959 attached
|
||||
@@ -637,9 +412,6 @@ strace: Process 15959 attached
|
||||
restart_syscall(<... resuming interrupted read ...>) = ?
|
||||
|
||||
+++ killed by SIGKILL +++
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<h2>知识详解:信号的两个系统调用</h2>
|
||||
@@ -663,21 +435,12 @@ restart_syscall(<... resuming interrupted read ...>) = ?
|
||||
<pre><code>NAME
|
||||
|
||||
kill - send signal to a process
|
||||
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
# include <sys/types.h>
|
||||
|
||||
# include <signal.h>
|
||||
|
||||
|
||||
|
||||
int kill(pid_t pid, int sig);
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>我们知道了发送信号的系统调用之后,再来看另一个系统调用,也就是 signal() 系统调用这个函数,它可以给信号注册 handler。</p>
|
||||
@@ -689,9 +452,6 @@ SYNOPSIS
|
||||
NAME
|
||||
|
||||
signal - ANSI C signal handling
|
||||
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
# include <signal.h>
|
||||
@@ -699,9 +459,6 @@ SYNOPSIS
|
||||
typedef void (*sighandler_t)(int);
|
||||
|
||||
sighandler_t signal(int signum, sighandler_t handler);
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>在容器 init 进程的第一讲里,我们学过进程对每种信号的处理,包括三个选择:调用系统缺省行为、捕获、忽略。而这里的选择,其实就是程序中如何去调用 signal() 这个系统调用。</p>
|
||||
@@ -731,27 +488,15 @@ SYNOPSIS
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
||||
{
|
||||
|
||||
|
||||
|
||||
...
|
||||
|
||||
signal(SIGTERM, sig_handler);
|
||||
|
||||
...
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>我们再来看看第三个选择,如果要让进程“忽略”一个信号,我们就要通过 signal() 这个系统调用,为这个信号注册一个特殊的 handler,也就是 SIG_IGN 。</p>
|
||||
@@ -791,13 +536,7 @@ int main(int argc, char *argv[])
|
||||
# include <errno.h>
|
||||
|
||||
# include <signal.h>
|
||||
|
||||
|
||||
|
||||
typedef void (*sighandler_t)(int);
|
||||
|
||||
|
||||
|
||||
void sig_handler(int signo)
|
||||
|
||||
{
|
||||
@@ -811,17 +550,11 @@ void sig_handler(int signo)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
||||
{
|
||||
|
||||
sighandler_t h_ret;
|
||||
|
||||
|
||||
|
||||
h_ret = signal(SIGKILL, sig_handler);
|
||||
|
||||
if (h_ret == SIG_ERR) {
|
||||
@@ -831,13 +564,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
# ./reg_sigkill
|
||||
|
||||
SIG_ERR: Invalid argument
|
||||
@@ -851,13 +578,7 @@ SIG_ERR: Invalid argument
|
||||
<pre><code># include <stdio.h>
|
||||
|
||||
# include <signal.h>
|
||||
|
||||
|
||||
|
||||
typedef void (*sighandler_t)(int);
|
||||
|
||||
|
||||
|
||||
void sig_handler(int signo)
|
||||
|
||||
{
|
||||
@@ -871,13 +592,7 @@ void sig_handler(int signo)
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
||||
{
|
||||
@@ -885,17 +600,11 @@ int main(int argc, char *argv[])
|
||||
//Ignore SIGTERM, and send SIGTERM
|
||||
|
||||
// to process itself.
|
||||
|
||||
|
||||
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
|
||||
printf("Ignore SIGTERM\n\n");
|
||||
|
||||
kill(0, SIGTERM);
|
||||
|
||||
|
||||
|
||||
//Catch SIGERM, and send SIGTERM
|
||||
|
||||
// to process itself.
|
||||
@@ -905,9 +614,6 @@ int main(int argc, char *argv[])
|
||||
printf("Catch SIGTERM\n");
|
||||
|
||||
kill(0, SIGTERM);
|
||||
|
||||
|
||||
|
||||
//Default SIGTERM. In sig_handler, it sets
|
||||
|
||||
//SIGTERM handler back to default one.
|
||||
@@ -915,15 +621,9 @@ int main(int argc, char *argv[])
|
||||
printf("Default SIGTERM\n");
|
||||
|
||||
kill(0, SIGTERM);
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>我们一起来总结一下刚才讲的两个系统调用:</p>
|
||||
@@ -1011,19 +711,10 @@ int main(int argc, char *argv[])
|
||||
<p>我给你举个具体的例子说明,从下面的这段代码中,我们可以看到除了 SIGCHLD 这个信号外,tini 会把其他所有的信号都转发给它的子进程。</p>
|
||||
|
||||
<pre><code>int wait_and_forward_signal(sigset_t const* const parent_sigset_ptr, pid_t const child_pid) {
|
||||
|
||||
|
||||
|
||||
siginfo_t sig;
|
||||
|
||||
|
||||
|
||||
if (sigtimedwait(parent_sigset_ptr, &sig, &ts) == -1) {
|
||||
|
||||
switch (errno) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -1059,31 +750,19 @@ int main(int argc, char *argv[])
|
||||
} else {
|
||||
|
||||
PRINT_FATAL("Unexpected error when forwarding signal: '%s'", strerror(errno));
|
||||
|
||||
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>那么我们在这里明确一下,怎么解决停止容器的时候,容器内应用程序被强制杀死的问题呢?</p>
|
||||
@@ -1113,13 +792,7 @@ int main(int argc, char *argv[])
|
||||
<pre><code class="language-c"># include <stdio.h>
|
||||
|
||||
# include <signal.h>
|
||||
|
||||
|
||||
|
||||
typedef void (*sighandler_t)(int);
|
||||
|
||||
|
||||
|
||||
void sig_handler(int signo)
|
||||
|
||||
{
|
||||
@@ -1135,29 +808,17 @@ void sig_handler(int signo)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
||||
{
|
||||
|
||||
|
||||
|
||||
//Ignore SIGTERM, and send SIGTERM
|
||||
|
||||
// to process itself.
|
||||
|
||||
|
||||
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
|
||||
printf("Ignore SIGTERM\n\n");
|
||||
|
||||
kill(0, SIGTERM);
|
||||
|
||||
|
||||
|
||||
//Catch SIGERM, and send SIGTERM
|
||||
|
||||
// to process itself.
|
||||
@@ -1171,9 +832,6 @@ int main(int argc, char *argv[])
|
||||
kill(0, SIGTERM);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Default SIGTERM. In sig_handler, it sets
|
||||
|
||||
//SIGTERM handler back to default one.
|
||||
@@ -1181,15 +839,9 @@ int main(int argc, char *argv[])
|
||||
printf("Default SIGTERM\n");
|
||||
|
||||
kill(0, SIGTERM);
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>欢迎留言和我分享你的想法和疑问。如果读完这篇文章有所收获,也欢迎你分享给自己的朋友,共同学习和进步。</p>
|
||||
@@ -1213,9 +865,6 @@ int main(int argc, char *argv[])
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1223,9 +872,6 @@ int main(int argc, char *argv[])
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||||
|
||||
</div>
|
||||
@@ -1241,17 +887,11 @@ int main(int argc, char *argv[])
|
||||
<script>
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
|
||||
|
||||
|
||||
function gtag() {
|
||||
|
||||
dataLayer.push(arguments);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-NPSEEVD756');
|
||||
@@ -1277,9 +917,6 @@ int main(int argc, char *argv[])
|
||||
setCookie("lastPath", path)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setCookie(cname, cvalue) {
|
||||
|
||||
var d = new Date();
|
||||
@@ -1291,9 +928,6 @@ int main(int argc, char *argv[])
|
||||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getCookie(cname) {
|
||||
|
||||
var name = cname + "=";
|
||||
@@ -1311,12 +945,6 @@ int main(int argc, char *argv[])
|
||||
return "";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user