后退按钮

“后退按钮” vue methods: { goBack(){ let state = { title: '', url: window.location.href }; window.history.pushState(state, state.title, state.url); } }, mounted() { if (window.history && window.history.pushState) { history.pushState(null, null, document.URL); //这里有没有都无所谓,最好是有以防万一 window.addEventListener('popstate', this.goBack, false); // 回退时执行goback方法 } }, // 页面销毁时,取消监听。否则其他vue路由页面也会被监听 destroyed(){ window.removeEventListener('popstate', this.goBack, false); } https://www.jianshu.com/p/9ee6be02d687 https://blog.csdn.net/qq_34179086/article/details/88081575

2021-04-23 · 1 min · 46 words · -

snap

snap 安装 snap 的过程还是需要些内存的, 我有个虚拟机剩余内存 230M, snap 安装失败… almalinux sudo dnf install epel-release sudo dnf upgrade dnf install snapd --enablerepo=epel -y almalinux sudo dnf install epel-release sudo dnf config-manager --set-enable epel sudo dnf upgrade sudo dnf install snapd # ubuntu: Unable to update "Snap Store": cannot refresh "snap-store": snap "snap-store" has running apps snap-store --quit # 列出已经安装的 snap 包 sudo snap list # 列出所有已安装的版本 snap list --all vlc # update all Snap packages sudo snap refresh # Check for snap changes sudo snap changes sudo snap abort <number> archlinux yay -S snapd sudo systemctl enable --now snapd.socket sudo systemctl start snapd.socket sudo ln -s /var/lib/snapd/snap /snap sudo snap install another-redis-desktop-manager http proxy $ sudo snap set system proxy.http="http://<proxy_addr>:<proxy_port>" $ sudo snap set system proxy.https="http://<proxy_addr>:<proxy_port>" https://blog.csdn.net/omaidb/article/details/120581033 ...

2021-04-22 · 1 min · 164 words · -

fork exec system()

“fork exec system()” system()、exec()、fork()三个与进程有关的函数的比较 启动新进程 (system函数) system() 函数可以启动一个新的进程。 int system (const char *string ) 这个函数的效果就相当于执行sh –c string。 一般来说,使用system函数远非启动其他进程的理想手段,因为它必须用一个shell来启动需要的程序。这样对shell的安装情况,以及shell的版本依赖性很大。 system函数的特点: 建立独立进程,拥有独立的代码空间,内存空间 等待新的进程执行完毕,system才返回。(阻塞) 替换进程映像 (exec函数) exec函数可以用来替换进程映像。执行exec系列函数后,原来的进程将不再执行,新的进程的PID、PPID和nice值与原先的完全一样。其实执行exec系列函数所发生的一切就是,运行中的程序开始执行exec调用中指定的新的可执行文件中的代码。 exec函数的特点: 当进程调用一种exec函数时,源进程完全由新程序代换,而新程序则从其main函数开始执行。因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用另一个新程序替换了当前进程的正文、数据、堆和栈段。特别地,在原进程中已经打开的文件描述符,在新进程中仍将保持打开,除非它们的"执行时关闭标志" (close on exec flag) 被置位。任何在原进程中已打开的目录流都将在新进程中被关闭。 复制进程映像 (fork函数) fork函数 头文件 #include<unistd.h> #include<sys/types.h> 函数原型 pid_t fork( void); 返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1 关于fork函数的作用,《Linux程序设计》中是这样解释的: 我们可以通过调用fork创建一个新进程。这个系统调用复制当前进程,在进程表中新建一个新的表项,新表项中的许多属性与当前进程是相同的。新进程几乎与元进程一模一样,执行的代码也完全相同,但是新进程有自己的数据空间、环境和文件描述符。 这个解释其实过于笼统,很多细节问题都没有说。下面就简单说一下调用fork时发生的一些细节问题。或者叫fork函数的特点: 首先,现在的 UNIX 系统和 Linux 系统都采用写时复制技术 (COW: Copy On Write) 。使用这种技术,当调用 fork 函数时,新的进程只是拥有自己的虚拟内存空间,而没有自己的物理内存空间。 新进程共享源进程的物理内存空间。 而且新内存的虚拟内存空间几乎就是源进程虚拟内存空间的一个复制。 我们知道,进程空间可以简单地分为程序段 (正文段) 、数据段、堆和栈四部分 (简单这样理解) 。采用写时复制的fork函数,当执行完fork后的一定时间内,新的进程 (子进程) 和源进程的进程空间关系如下图: fork执行时,Linux 内核会为新的进程 P2 创建一个虚拟内存空间,而新的虚拟空间中的内容是对 P1 虚拟内存空间中的内容的一个拷贝。而 P2 和 P1 共享原来 P1 的物理内存空间。 ...

2021-04-18 · 6 min · 1141 words · -

写时复制 (Copy-on-write: COW)

“写时复制 (Copy-on-write: COW) " 写入时复制 (英语: Copy-on-write,简称COW) 是一种计算机程序设计领域的优化策略。其核心思想是,如果有多个调用者 (callers) 同时请求相同资源 (如内存或磁盘上的数据存储) ,他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本 (private copy) 给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的 (transparently) 。此作法主要的优点是如果调用者没有修改该资源,就不会有副本 (private copy) 被创建,因此多个调用者只是读取操作时可以共享同一份资源。 在java中的应用举例 java中有两个类: CopyOnWriteArrayList、CopyOnWriteArraySet使用了写时复制技术手段,CopyOnWriteArrayList的实现: A thread-safe variant of java.util.ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array. 在多线程环境,凡是读操作都没有进行加锁操作,而写操作都会在锁的保护下复制一份数据,在复制的数据上做修改,修改完后,再把底层数组的引用指向修改后的新数组。 复制数据意味着需要浪费内存空间,所以在读 写少的并发场景下比较合适。 /** * The lock protecting all mutators. (We have a mild preference * for builtin monitors over ReentrantLock when either will do.) */ final transient Object lock = new Object(); ...

2021-04-18 · 6 min · 1273 words · -

task_struct, 进程描述符, 进程控制块 (PCB)

“task_struct, 进程描述符, 进程控制块 (PCB)” task struct, task_struct, 进程描述符, 进程控制块 (PCB) https://github.com/torvalds/linux/blob/master/include/linux/sched.h 进程是资源分配的基本单位。 进程控制块 (Process Control Block, PCB) 描述进程的基本信息和运行状态,所谓的创建进程和撤销进程,都是指对 PCB 的操作。 进程是处于执行期的程序以及它所管理的资源 (如打开的文件、挂起的信号、进程状态、地址空间等等) 的总称。注意,程序并不是进程,实际上两个或多个进程不仅有可能执行同一程序,而且还有可能共享地址空间等资源。 Linux内核通过一个被称为进程描述符的task_struct结构体来管理进程,这个结构体包含了一个进程所需的所有信息。它定义在include/linux/sched.h文件中。 谈到task_struct结构体,可以说她是linux内核源码中最复杂的一个结构体了,成员之多,占用内存之大。 鉴于她的复杂,我们不能简单的亵渎,而是要深入"窥探". 下面来慢慢介绍这些复杂成员 进程状态 volatile long state; /-1 unrunnable, 0 runnable, >0 stopped/ state成员的可能取值如下 参见http://lxr.free-electrons.com/source/include/linux/sched.h?v=4.5#L207 /* Task state bitmask. NOTE! These bits are also encoded in fs/proc/array.c: get_task_state(). We have two separate sets of flags: task->state is about runnability, while task->exit_state are about the task exiting. Confusing, but this way modifying one set can’t modify the other one by mistake. */ #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE 2 #define __TASK_STOPPED 4 #define __TASK_TRACED 8 /in tsk->exit_state/ #define EXIT_DEAD 16 #define EXIT_ZOMBIE 32 #define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD) ...

2021-04-17 · 14 min · 2911 words · -

pmod, 实模式和保护模式

“pmod, 实模式和保护模式” 实模式和保护模式都是CPU的工作模式,而CPU的工作模式是指CPU的寻址方式、寄存器大小等用来反应CPU在该环境下如何工作的概念。 实模式 实模式出现于早期 8088CPU时期。当时由于CPU的性能有限,一共只有20位地址线 (所以地址空间只有1MB) ,以及8个16位的通用寄存器,以及4个16位的段寄存器。所以为了能够通过这些16位的寄存器去构成20位的主存地址,必须采取一种特殊的方式。当某个指令想要访问某个内存地址时,它通常需要用下面的这种格式来表示: (段基址: 段偏移量) 其中第一个字段是段基址,它的值是由段寄存器提供的(一般来说,段寄存器有6种,分别为cs,ds,ss,es,fs,gs,这几种段寄存器都有自己的特殊意义,这里不做介绍)。 第二字段是段内偏移量,代表你要访问的这个内存地址距离这个段基址的偏移。它的值就是由通用寄存器来提供的,所以也是16位。那么两个16位的值如何组合成一个20位的地址呢?CPU采用的方式是把段寄存器所提供的段基址先向左移4位。这样就变成了一个20位的值,然后再与段偏移量相加。 即: 物理地址 = 段基址«4 + 段内偏移 所以假设段寄存器中的值是0xff00,段偏移量为0x0110。则这个地址对应的真实物理地址是 0xff00«4 + 0x0110 = 0xff110。 由上面的介绍可见,实模式的"实"更多地体现在其地址是真实的物理地址。 保护模式 随着CPU的发展,CPU的地址线的个数也从原来的20根变为现在的32根,所以可以访问的内存空间也从1MB变为现在4GB,寄存器的位数也变为32位。所以实模式下的内存地址计算方式就已经不再适合了。所以就引入了现在的保护模式,实现更大空间的,更灵活也更安全的内存访问。 在保护模式下,CPU的32条地址线全部有效,可寻址高达4G字节的物理地址空间; 但是我们的内存寻址方式还是得兼容老办法(这也是没办法的,有时候是为了方便,有时候是一种无奈),即(段基址: 段偏移量) 的表示方式。当然此时CPU中的通用寄存器都要换成32位寄存器(除了段寄存器,原因后面再说)来保证寄存器能访问所有的4GB空间。 我们的偏移值和实模式下是一样的,就是变成了32 位而已,而段值仍旧是存放在原来16位的段寄存器中,但是这些段寄存器存放的却不再是段基址了,毕竟之前说过实模式下寻址方式不安全,我们在保护模式下需要加一些限制,而这些限制可不是一个寄存器能够容纳的,于是我们把这些关于内存段的限制信息放在一个叫做全局描述符表(GDT)的结构里。全局描述符表中含有一个个表项,每一个表项称为段描述符。而段寄存器在保护模式下存放的便是相当于一个数组索引的东西,通过这个索引,可以找到对应的表项。段描述符存放了段基址、段界限、内存段类型属性(比如是数据段还是代码段,注意一个段描述符只能用来定义一个内存段)等许多属性,具体信息见下图: 图1 段描述符格式 其中,段界限表示段边界的扩张最值,即最大扩展多少或最小扩展多少,用20位来表示,它的单位可以是字节,也可以是4KB,这是由G位决定的(G为1时表示单位为4KB)。 实际段界限边界值=(描述符中的段界限+1)* (段界限的单位大小(即字节或4KB))-1,如果偏移地址超过了段界限,CPU会抛出异常。 全局描述符表位于内存中,需要用专门的寄存器指向它后, CPU 才知道它在哪里。这个专门的寄存器便是GDTR(一个48位的寄存器),专门用来存储 GDT 的内存地址及大小。 最后我们再介绍一下一个新的概念: 段的选择子。段寄存器 CS、 DS、 ES、 FS、 GS、 SS,在实模式下时,段中存储的是段基地址,即内存段的起始地址。 而在保护模式下时,由于段基址已经存入了段描述符中,所以段寄存器中再存放段基址是没有意义的,在段寄存器中存入的是一个叫作选择子的东西。选择子"基本上"是个索引值,虽然它还有其他内容,不过作为初学者暂时忽略也没太大关系。由于段寄存器是 16 位,所以选择子也是 16 位,在其低 2 位即第 0~1 位, 用来存储 RPL,即请求特权级(有兴趣的可以了解一下,不想了解的忽略即可,跟用户态和内核态相关的),可以表示 0、 1、 2、 3 四种特权级。在选择子的第 2 位是 TI 位,即 Table Indicator,用来指示选择子是在 GDT 中,还是 LDT 中索引描述符。 TI 为 0 表示在 GDT 中索引描述符, TI 为 1 表示在 LDT 中索引描述符。选择子的高 13 位,即第 3~15 位是 描述符的索引值,用此值在 GDT 中索引描述符。前面说过 GDT 相当于一个描述符数组,所以此选择子中的索引值就是 GDT 中的下标。选择子结构如下: ...

2021-04-17 · 2 min · 254 words · -

系统调用, System Call

“系统调用, System Call” 计算机系统的各种硬件资源是有限的,在现代多任务操作系统上同时运行的多个进程都需要访问这些资源,为了更好的管理这些资源进程是不允许直接操作的,所有对这些资源的访问都必须有操作系统控制。也就是说操作系统是使用这些资源的唯一入口,而这个入口就是操作系统提供的系统调用 (System Call) 。在linux中系统调用是用户空间访问内核的唯一手段,除异常和陷入外,他们是内核唯一的合法入口。 一般情况下应用程序通过应用编程接口API,而不是直接通过系统调用来编程。在Unix世界,最流行的API是基于POSIX标准的。 操作系统一般是通过中断从用户态切换到内核态。中断就是一个硬件或软件请求,要求CPU暂停当前的工作,去处理更重要的事情。比如,在x86机器上可以通过int指令进行软件中断,而在磁盘完成读写操作后会向CPU发起硬件中断。 中断有两个重要的属性,中断号和中断处理程序。中断号用来标识不同的中断,不同的中断具有不同的中断处理程序。在操作系统内核中维护着一个中断向量表 (Interrupt Vector Table) ,这个数组存储了所有中断处理程序的地址,而中断号就是相应中断在中断向量表中的偏移量。 一般地,系统调用都是通过软件中断实现的,x86系统上的软件中断由int $0x80指令产生,而128号异常处理程序就是系统调用处理程序system_call(),它与硬件体系有关,在entry.S中用汇编写。接下来就来看一下Linux下系统调用具体的实现过程。 为什么需要系统调用 linux内核中设置了一组用于实现系统功能的子程序,称为系统调用。系统调用和普通库函数调用非常相似,只是系统调用由操作系统核心提供,运行于内核态,而普通的函数调用由函数库或用户自己提供,运行于用户态。 一般的,进程是不能访问内核的。它不能访问内核所占内存空间也不能调用内核函数。CPU硬件决定了这些 (这就是为什么它被称作"保护模式" (详细参见深入理解计算机系统-之-内存寻址 (二) –存储保护机制 (CPU实模式与保护模式) ) ) 。 为了和用户空间上运行的进程进行交互,内核提供了一组接口。透过该接口,应用程序可以访问硬件设备和其他操作系统资源。这组接口在应用程序和内核之间扮演了使者的角色,应用程序发送各种请求,而内核负责满足这些请求(或者让应用程序暂时搁置)。实际上提供这组接口主要是为了保证系统稳定可靠,避免应用程序肆意妄行,惹出大麻烦。 系统调用在用户空间进程和硬件设备之间添加了一个中间层。该层主要作用有三个: 它为用户空间提供了一种统一的硬件的抽象接口。比如当需要读些文件的时候,应用程序就可以不去管磁盘类型和介质,甚至不用去管文件所在的文件系统到底是哪种类型。 系统调用保证了系统的稳定和安全。作为硬件设备和应用程序之间的中间人,内核可以基于权限和其他一些规则对需要进行的访问进行裁决。举例来说,这样可以避免应用程序不正确地使用硬件设备,窃取其他进程的资源,或做出其他什么危害系统的事情。 每个进程都运行在虚拟系统中,而在用户空间和系统的其余部分提供这样一层公共接口,也是出于这种考虑。如果应用程序可以随意访问硬件而内核又对此一无所知的话,几乎就没法实现多任务和虚拟内存,当然也不可能实现良好的稳定性和安全性。在Linux中,系统调用是用户空间访问内核的惟一手段;除异常和中断外,它们是内核惟一的合法入口。 Linux 的系统调用主要有以下这些: Task Commands 进程控制 fork(); exit(); wait(); 进程通信 pipe(); shmget(); mmap(); 文件操作 open(); read(); write(); 设备操作 ioctl(); read(); write(); 信息维护 getpid(); alarm(); sleep(); 安全 chmod(); umask(); chown(); 从"read"看系统调用的耗时 fread和read有何不同 先看两段代码: fread #include<stdio.h> #include<stdlib.h> FILE* pf = fopen("test.txt", "r"); char buf[2] = { 0 }; int ret = 0; do { ret = fread(buf, 1, 1, pf); } while (ret); read #include<stdio.h> #include<stdlib.h> FILE* pf = fopen("test.txt", "r"); char buf[2] = { 0 }; int ret = 0; do { ret = read(buf, 1, 1, pf); } while (ret); 两个文件的功能完全一样,打开同一个名为test.file的文件,并逐字节地读取整个文件。 将它们编译后得到的可执行程序fread和read分别在同一台PC (linux系统) 上执行, fread与read的耗时相差数十倍之多!可见啊~read一个字节这种写法是相当不可取的! ...

2021-04-15 · 8 min · 1685 words · -

ap

“ap” 商用 AP 厂商: aruba/安移通, ruckus/优科 … ruckus 的 unleashed 系列AP, unleashed 系列最大的优势是: Wi-Fi非常稳定,快速漫游、无缝切换、 5G占比调节等都是基本操作 配置界面非常友好,由浅入深、简单易懂,即使是新手也完全可以应付的来 刷机省钱。ruckus的AP对自主刷固件支持,比如R310刷R310 unleashed版本,前者售价850左右,后者950左右?没有商业注册限制,在ruckus官网注册就可以下载固件 闲鱼上很多R系列的再售,价格不高 (本文三台 两个买家购入 带标签的翻车了 且卖家不退换 所以没打码) 本教程用的是 Ruckus R310,三只一共价格在1000元左右,覆盖办公室面积400平+,浏览器为Safari,其他有unleashed固件的AP型号通用,但由于功耗不同有可能需要用到功率更大的802.3at的POE标准的交换机 如果有更高阶的需求,可以考虑R5X0 R6X0 R7X0系列,其中R730 R750 R650是支持Wi-Fi6的 https://zhuanlan.zhihu.com/p/118554342 RUCKUS H320 https://webresources.ruckuswireless.com/datasheets/h320/ds-commscope-h320-zh-cn.html H350 https://support.ruckuswireless.com/products/191-ruckus-h350?open=document#sort=relevancy&f:@source=[Documentation]&f:@commonproducts=[H350]

2021-04-10 · 1 min · 38 words · -

network topology

“network topology” @startuml [光猫] as onu package "J4100 \n 4网口工控机" { interface "ETH1\nenp1s0" as j4100Eth1 interface "ETH2\nenp2s0" as j4100Eth2 interface "ETH2\neno1" as j4100Eth3 interface "ETH3\nenp4s0" as j4100Eth4 agent vmbr0 j4100Eth1 -down- vmbr0 j4100Eth3 -down- vmbr0 j4100Eth4 -down- vmbr0 agent vmbr1 j4100Eth2 -down- vmbr1 [Openwrt] as router router - vmbr0 vmbr1 -down- router } onu -down- j4100Eth2 @enduml

2021-04-03 · 1 min · 57 words · -

dm-crypt, 加密

dm-crypt, 加密 dm-crypt 是整合到 linux 内核中的,而它的命令行前端 cryptsetup, 在大多数主流的 linux 发行版中都会自带 LUKS = Linux Unified Key Setup commands # 将分区设置为加密的 LUKS 分区, 这个时候会对磁盘分区进行全盘覆写,所以速度会比较慢 # luksFormat: 初始化并格式化一个分区以便使用 LUKS 加密。 # luksOpen: 打开一个已加密的 LUKS 分区,使其可用。 # luksClose: 关闭一个已打开的 LUKS 分区。 # status: 查看加密设备的状态。 cryptsetup luksFormat /dev/nvme0n1p1 cryptsetup luksOpen /dev/nvme0n1pX cryptroot # 打开加密的 LUKS 分区, 映射加密分区到 nvme0n1p1_encrypted, # 将加密分区映射到逻辑分区 /dev/mapper/nvme0n1p8_crypt cryptsetup open /dev/nvme0n1p1 nvme0n1p1_encrypted # 重设 PV 上加密层的大小 # https://unix.stackexchange.com/questions/322905/what-does-cryptsetup-resize-do-if-luks-doesnt-store-partition-size sudo cryptsetup resize /dev/mapper/devicemappername 用 cryptsetup 创建 LUKS 的虚拟加密盘 (逻辑卷) 在前一个章节,已经介绍了"对物理分区的加密"。其实 cryptsetup 也可以支持虚拟加密盘 (逻辑加密盘) ——类似于 TrueCrypt 那样。 ...

2021-03-30 · 1 min · 205 words · -

X Server, XServer

“X Server, XServer” 背景 大多数时候我们不希望在服务器上安装图形界面,但有时候有些程序需要图形界面,比如安装Oracle的时候。此时,可以配置让Linux使用远程的X Server进行图形界面显示。 首先要明确的是Linux X Window System的基本原理,X是一个开放的协议规范,当前版本为11,俗称X11。X Window System由客户端和服务端组成,服务端X Server负责图形显示,而客户端库X Client根据系统设置的DISPLAY环境变量,将图形显示请求发送给相应的X Server。 因此,我们只需要在远端开启一个X Server,并在目标机器上相应的设置DISPLAY变量,即可完成图形的远程显示。 command export DISPLAY=192.168.97.183:0 ~/.xinitrc是X的配置文件,在 /etc/skel/.xinitrc 有它的模板,可以把它copy到用户目录下面: $ cp /etc/skel/.xinitrc ~ 以".“开头的文件,通常是隐藏文件,用普通的"ls"是查看不到的,若想查看,需要用"ls -A"命令。 其次,以"rc"结尾的文件代表它是运行的命令行或者是配置文件。又因为它通常控制着程序的运行,所以也通常叫着"run control” https://blog.csdn.net/vic_qxz/article/details/79073558

2021-03-29 · 1 min · 32 words · -

kux

“kux” kux 转 mp4 https://zhuanlan.zhihu.com/p/111764932 安装youku客户端 执行脚本 @echo off setlocal enabledelayedexpansion set ffmpeg="C:\Program Files (x86)\YouKu\YoukuClient\nplayer\ffmpeg.exe" if exist %ffmpeg% ( for /r . %%i in (*.kux) do ( %ffmpeg% -y -i "%%i" -c:a copy -c:v copy -threads 2 "%%~dpni.mp4" ) ) else echo pause

2021-03-27 · 1 min · 43 words · -

arp table, arp 表

“arp table, arp 表” ARP表(Address Resolution Table) ARP协议 首先明确一点,在以太网环境下,同一个网段的主机之间需要知道对方的MAC地址,才能进行通信。 上一节介绍了交换机的工作原理,了解到交换机是根据MAC寻址,查表确认输出端口以完成本节点转发任务的。看到这里其实应该可以抛出从一开始就被我们忽视了的问题: 在初始构造数据包准备发送时,源主机究竟要如何获得目的主机网络设备MAC地址的呢?这时,就需要使用到ARP协议。在网络拓扑中的每个节点或说主机上,实际都维护有一张ARP表,它记录着主机的IP地址(网络地址)到MAC地址(物理地址)的映射关系。 ARP协议,即地址解析协议,它是一个网络层协议,运行在各网络节点上,负责完成主机IP地址到MAC地址的映射。 ip neighbour–neighbour/arp 表管理命令 ip neighbour–neighbour/arp 表管理命令 缩写 neighbour、neighbor、neigh、n 命令 add、change、replace、delete、fulsh、show(或者list) ip neighbour add -----添加一个新的邻接条目 ip neighbour change -----修改一个现有的条目 ip neighbour replace -----替换一个已有的条目 缩写: add、a;change、chg;replace、repl 例: 在设备eth0上,为地址 10.0.0.3 添加一个 permanent ARP条目: ip neigh add 10.0.0.3 lladdr 0:0:0:0:0:1 dev eth0 nud perm 例: 把状态改为 reachable ip neigh chg 10.0.0.3 dev eth0 nud reachable ip neighbour delete ---删除一个邻接条目 例: 删除设备eth0上的一个ARP条目10.0.0.3 ip neigh del 10.0.0.3 dev eth0 ip neighbour show -- 显示网络邻居的信息. 缩写: show、list、sh、ls 例: # ip -s n ls 193.233.7.254 193.233.7.254. dev eth0 lladdr 00:00:0c:76:3f:85 ref 5 used 12/13/20 nud reachable ...

2021-03-23 · 1 min · 116 words · -

cypress

cypress npm install cypress --save-dev npx cypress open install cypress for project npm install --save-dev cypress # 执行cypress install, 把cypress安装到 ~/.cache/Cypress node_modules/cypress/bin/cypress install install MySQL npm install MySQL --save-dev 配置MySQL连接信息, 修改 cypress.json 成这样 { "pluginsFile": "tests/e2e/plugins/index.js", "env": { "db": { "host": "192.168.1.xxx", "user": "user0", "password": "password0", "database": "database0" } } } 配置 tests/e2e/plugins/index.js const MySQL = require('MySQL') function queryTestDb (query, config) { const connection = MySQL.createConnection(config.env.db) connection.connect() return new Promise((resolve, reject) => { connection.query(query, (error, results) => { if (error) reject(error) else { connection.end() console.log(results) console.log('connected') return resolve(results) } }) }) } module.exports = (on, config) => { on('task', { log (message) { console.log(message) return null } }) on('task', { queryDb: query => { return queryTestDb(query, config) } }) return Object.assign({}, config, { fixturesFolder: 'tests/e2e/fixtures', integrationFolder: 'tests/e2e/specs', screenshotsFolder: 'tests/e2e/screenshots', videosFolder: 'tests/e2e/videos', supportFile: 'tests/e2e/support/index.js' }) } command timeout cy.visit('/', { timeout: 3000 }) type cy.get('[data-cy=user-name]').type('user0') click cy.get('[data-cy=login]').click() contains cy.get('[data-cy=list]').find('tbody>tr').first().contains('td', 'id0') clear cy.get('[data-cy=plate]').clear() 页面元素数量, 3个 text0 文字 cy.contains('span', 'text0').should('have.length', 3) 比较文本 cy.get('[data-cy=foo]').should('have.text',"0") cy.get('[data-cy=foo]').should('not.have.text',"0") sql cy.task('queryDb', 'DELETE FROM `table0`').then(res => { cy.log(res) }) count cy.task('queryDb', 'SELECT COUNT(*) AS count FROM table0 WHERE field0=\'value0\'').then(res => { expect(res[0].count).to.equal(1) }) 配置 NODE_ENV "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "test:unit": "vue-cli-service test:unit", "test:e2e": "NODE_ENV=development vue-cli-service test:e2e", "lint": "vue-cli-service lint" },

2021-03-16 · 1 min · 205 words · -

vuetify

“vuetify” 安装相应包 yarn add @mdi/font -D # roboto字体其实不要也行,就英文的一套字体而已 yarn add typeface-roboto -D plugins/vuetify.js import Vue from 'vue'; import Vuetify from 'vuetify/lib'; import zhHans from 'vuetify/es5/locale/zh-Hans' // 引入中文语言包 import 'typeface-roboto/index.css' // 引入本地的Roboto字体资源 import '@mdi/font/css/materialdesignicons.css' // 引入本地的Material Design Icons资源 Vue.use(Vuetify); export default new Vuetify({ lang:{ locales: {zhHans}, current: 'zhHans' }, icons:{ iconfont: 'mdi', // 设置使用本地的icon资源 } }); 模板中使用 <template> <v-icon>mdi-account-circle</v-icon> </div> </template> <script> export default { } </script> replace google font,mdi font with local resource 注释掉public/index.html中引用的字体 ...

2021-03-16 · 1 min · 77 words · -

vnc rdp

vnc rdp VNC是什么? 简单来说,所谓的 VNC(Virtual Network Computing )是一种图形化的桌面共享系统,它使用远程帧缓冲协议 (RFB) 来远程控制另一台计算机。它将键盘和鼠标事件从一台计算机传输到另一台计算机,通过网络向另一个方向转发图形屏幕更新。 类似这样的技术VNC不是绝无仅有,但VNC 的流行和普及却因为其具有的过人之处 – VNC是平台无关的—— 有多种客户端和服务器的实现,几乎涵盖了所有的主流平台。甚至一些VNC的实现被称“无客户端”,这是因为不需要安装插件或客户端软件而,而是依靠HTML5技术,只需要一个浏览器就可以访问远程桌面了。 VNC 是开源的—— VNC最初是在英国剑桥的Olivetti & Oracle研究实验室开发的。原始的VNC源代码和许多现代的衍生品在GNU通用公共许可证下是开放源码的。 VNC的协议是简单、普适的—— VNC使用的是 RFB(Remote Framebuffer) 协议。这是一个开放且简单的协议。因为它在framebuffer级别工作,协议是基于像素的所以适用于所有窗口系统和应用程序,包括Microsoft Windows、macOS和X Window系统。这个协议的性能表现是很出色的。 RDP 又是什么? 有过 Windows 使用经验的人对于远程桌面(Remote Desktop Protocol ,RDP)一定不会陌生。RDP 是由微软公司开发的一种专有协议,它为用户提供了通过网络连接到另一台计算机的图形界面。在使用上,用户需要使用 RDP 客户端软件,而在远程另一台计算机则需要运行 RDP 服务器软件。 VNC协议是基于像素的。尽管这带来了极大的灵活性,可以显示任何类型的桌面,但它的效率往往不如那些更好地理解底层图形布局(例 如: X11)或桌面(例如:RDP )的解决方案。这些协议以更简单的形式(例如:打开窗口)发送图形原语或高级命令,而 VNC 的 RFB 协议尽管支持压缩但只能是发送原始像素数据。 https://aws.amazon.com/cn/blogs/china/vnc-or-rdp-how-to-choose-a-remote-desktop-on-the-cloud/

2021-03-13 · 1 min · 49 words · -

Ant 风格路径表达式, ant style

Ant 风格路径表达式, ant style ANT通配符有三种: 通配符 说明 ? 匹配任何单字符 * 匹配0或者任意数量的字符 ** 匹配0或者更多的目录 例子: URL路径 说明 /app/*.x 匹配(Matches)所有在app路径下的.x文件 /app/p?ttern 匹配(Matches) /app/pattern 和 /app/pXttern,但是不包括/app/pttern /**/example 匹配(Matches) /app/example, /app/foo/example, 和 /example /app/**/dir/file.* 匹配(Matches) /app/dir/file.jsp, /app/foo/dir/file.html,/app/foo/bar/dir/file.pdf, 和 /app/dir/file.java /**/*.jsp 匹配(Matches)任何的.jsp 文件 最长匹配原则(has more characters) URL请求/app/dir/file.jsp,现在存在两个路径匹配模式/**/.jsp和/app/dir/.jsp,那么会根据模式/app/dir/*.jsp来匹配 作者: 芒果粑粑 链接: https://www.jianshu.com/p/189847a7d1c7 来源: 简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2021-03-05 · 1 min · 49 words · -

speed test cli, 测速

“speed test cli, 测速” https://www.speedtest.net/zh-Hans/apps/cli archlinux pacman -Sy speedtest-cli speedtest-cli --server=43752 --bytes https://github.com/sivel/speedtest-cli macos install speedtest-cli brew install speedtest-cli speedtest-cli --list

2021-03-01 · 1 min · 21 words · -

密码加密存储技术详解 (Password Storage Cheat Sheet)

密码加密存储技术详解 (Password Storage Cheat Sheet) 从最早的明文保存密码,到 md5 sha1 sha256 sha512 加密,到加 salt、加 pepper、多次 hash 计算,再到现代的密码加密算法Bcrypt PBKDF2 Argon2。在保护用户密码的过程中,软件工程师作出了巨大的努力,为网络安全的建设添砖加瓦。 本文详细的描述了密码加密存储技术涉及到的方方面面,并在最后给出了Java语言的实现代码。代码虽然简单,但其中原理却非常值得一读。 介绍 大多数用户在不同的网站或应用中使用相同的密码,因此当网站的数据库被盗取,存储的密码也不应该被攻击者获取。与密码学大多数领域一样,需要考虑很多因素;幸运的是,大多数现代编程语言和框架都提供了内置的功能来帮助存储密码,让问题变得简单很多。 本文章提供了与存储密码有关的各个方面的指导。简而言之: 使用Bcrypt。除非你有足够充分的理由不这么做。 设置合理的计算因子(work factor)。 使用盐Salt (现代算法会自动帮你这么做)。 考虑使用胡椒Pepper来提供额外的防御深度 (尽管单独使用它无法提供额外的安全特性)。 https://www.ujcms.com/knowledge/509.html Argon2 设计目标:Argon2 是目前最先进的密码哈希算法,专门设计用于对抗现代硬件攻击,包括暴力破解和 GPU 破解。它在 2015 年获得了密码哈希竞赛(Password Hashing Competition, PHC)中的冠军。 工作原理:Argon2 的设计包括内存硬化和迭代机制。它提供三种变体: Argon2d:强调防止 GPU 并行化攻击,适用于需要最大化时间复杂度的场景。 Argon2i:优化了对抗侧信道攻击,适用于对内存硬化要求较高的场景。 Argon2id:结合了 Argon2d 和 Argon2i 的优点,是最常用的版本。 优点: 高效的内存使用,适合防止使用大量并行计算能力(如 GPU)的破解。 可调整内存、时间和并行度,灵活性高。 通过设计抵抗 GPU 和 ASIC 攻击,非常适合现代硬件环境。 缺点:相比于 bcrypt 和 PBKDF2,Argon2 的实现较为复杂,可能会涉及更多的计算资源,尤其是内存要求较高。

2021-02-26 · 1 min · 64 words · -

tcp

tcp TCP将数据分解成网络数据包,并在每个数据包中添加少量数据。这些附加数据包括一个序列号,用于检测丢失或到达顺序不正确的数据包,以及一个校验和,可以检测数据包数据内的错误。当其中任何一个问题发生时,TCP使用自动重传请求 (ARQ)告诉发送方重新发送丢失或损坏的数据包。 https://luoguochun.cn/post/2016-09-23-tcp-fuck/ TCP 的连接标识是通过 “源IP + 源Port + 目标IP + 目标Port + 协议号“ 组成的唯一五元组,一旦其中一个参数发生变化,则需要重新创建新的 TCP 连接。 tcp协议是一个比较复杂的协议,对tcp协议深入理解的,真的非常少非常少;对tcp协议误理解或理解片面的,真的非常多非常多。当然这也包括自己在内,当然也可能包括这篇小结在内。 P.S.: 《TCP/IP详解卷1:协议》是介绍TCP/IP协议栈最经典的著作(神级已故人物W.Richard Stevens经典书籍之一),然而个人觉得这个"详解"对于tcp的介绍有点简略或者理解起来印象非深,读了一次,一次又一次,还是概念模糊。当然这也与中文译本烂得一塌糊涂有关。同时这本经典书籍也有了它的更新版,不同的是作者已经不是原来的神级人物,相同的是译文继续烂。 tcp协议头 tcp协议头 tcp基本协议头占用20个字节,协议中Header Length(4bits)中标明协议头的长度,含义是多少个32bit数据,该字段占用4位,所有整个tcp头最多可以占用60字节。当tcp建立时,主机会生成一个初始的序列号(ISN, Initial Sequence Number),在tcpdump程序抓取的报文中可以看到该初始Sequence,Sequence的生成方式有一定的算法,一般tcp分析很少关注。如果tcpdump查看报文,可以发现,第一个SYN包收到ACK后,后续的SEQ都变成了ISN的偏移量。如果是用大鲨鱼wireshark查看报文,则可以发现,seq总是从0开始,并提示这个值是相对值,大鲨鱼已经处理好这些细节。如: tcpdump seq wireshark seq tcp报文SYN ACK的计算如下: A -> B SYN J ACK K LEN L B -> A SYN K ACK J+L LEN M A -> B SYN J+L ACK K+M 需要注意到的是,注意,对于DATA LEN为0的,发送的SYN包和FIN包,需要消耗一个序号。为了提高传送的效率,ACK是支持累计的,也就是说没必要对每个SYN进行ACK。如: 发送端连续发送3个报文,那么接收端收到3个报文后,可以直接应答一个ACK。 tcp标志位 CWR(Congestion Window Reduced) & ECN (ECN-Echo, Explicit Congestion Notification) CWR 阻塞窗口已减少,意思是告诉对端我已经按照你的要求,进行阻塞窗口减少了,并启动阻塞算法来控制我的发包速度; ECN 显式阻塞窗口通知,意思通知发送方,我接收的报文出现了阻塞,请控制发包速度。也就是说,CWR 和 ECN 必须配合使用,CWR 是收到 ECN 的应答。此外,在tcp三次握手时,这两个标志表明tcp端是否支持ECN。如果建立连接一方支持,则在发送的SYN包,将 ECN 标志置为1,如果服务端也支持,则在ACK包只设置ECN。缘由: tcp建立连接后,报文经过经过路由或网关等网络设备后,在路由器或网关等网络设备出现阻塞时,路由器或网关等设备设置IP层的某个标志表明出现阻塞,这样接收可以明确知道报文出现了阻塞。然而,需要知道阻塞进行阻塞控制的是报文发送方而非接收方。所以接收方会在ACK报文中设置ECN标志,同时发送方在ACK中设置CWR标志,表明已经收到ECN,并进行了减少阻塞窗口操作和启用阻塞算法。 ...

2021-02-15 · 5 min · 1064 words · -