更新 node.js

[[Node.js]] How to Update Node.js to Latest Version (Linux, Ubuntu, OSX, Others) origin-link: How to Update Node.js to Latest Version (Linux, Ubuntu, OSX, Others) As with so many open-source technologies, Node.js is a fast-moving project. Minor updates come out every few weeks to boost stability and security among all version branches. Methods abound for updating Node on any operating system, so you don’t have an excuse to fall behind. We’ve compiled some of the simplest and most effective ways to install the newest version of Node on Linux-based, Windows, and macOS machines. Before you get started, check which version of Node.js you’re currently using by running node -v in a command line terminal. ...

栈的 Python 实现(列表)

Python [[Data Structure]] 栈的 Python 实现(列表) class Stack(object): """栈的 Python 列表实现 """ # 初始化对象,生成空列表 def __init__(self): self.item = [] # 判断栈是否为空,返回 True or False def isEmpty(self): return self.item == [] # 入栈方法,添加至列表尾部 def push(self, item): self.item.append(item) # 出栈方法,从队列尾部弹出,并返回弹出值 def pop(self): return self.item.pop() # 查栈顶元素方法,返回栈顶元素值,但不弹出 def peek(self): return self.item[len(self.item)-1] # 查看栈的大小方法,返回 int 值 def size(self): return len(self.item) def match_sympol(string): """ 利用栈的特性(后进先出),对三种常见括号进行匹配 对于左括号,直接压入栈,遇到右括号,弹出栈顶元素,若能一一对应,且最终栈为空,则完全匹配 """ s = Stack() flag = True index = 0 while index < len(string) and flag: symbol = string[index] if symbol in "({[": s.push(symbol) else: if s.isEmpty(): flag = False else: top = s.pop() if not matches_help(top, symbol): flag = False index += 1 if flag and s.isEmpty(): return True else: return False def matches_help(open, close): """ 匹配辅助函数 传入两个 char 参数,判断是否对应,返回 True or False """ opens = "({[" closes = ")}]" return opens.index(open) == closes.index(close) def ten2two(num): """ 十进制转二进制,原理是除二取余法 将十进制数除二取余数,将余数压入栈,直到十进制数为 0,然后栈逐个弹出 """ s = Stack() while num > 0: rem = num%2 s.push(rem) num = num//2 binString = "" while not s.isEmpty(): binString = binString + str(s.pop()) return binString def infixToPostfix(infixexpr): """ 中序表达式转后续表达式 中序表达式转换后续表达式有个简单的方法,先将中序表达式的每一次运算都加上括号,接着从右往左, 找到第一个算数符号替换掉最近的右括号,并将对应的左括号去除,继续往左执行,直到没有括号为止 具体过程: 1、创建一个名为 opstack 的空栈以保存运算符。给输出创建一个空列表。 2、通过使用字符串方法拆分将输入的中缀字符串转换为标记列表。 3、从左到右扫描标记列表。 如果标记是操作数,将其附加到输出列表的末尾。 如果标记是左括号,将其压到 opstack 上。 如果标记是右括号,则弹出 opstack,直到删除相应的左括号。将每个运算符附加到输出列表的末尾。 如果标记是运算符,*,/,+或 - ,将其压入 opstack。但是,首先删除已经在 opstack 中具有更高或相等优先级的任何运算符,并将它们加到输出列表中。 4、当输入表达式被完全处理时,检查 opstack。仍然在栈上的任何运算符都可以删除并加到输出列表的末尾。 理解过程可见:https://facert.gitbooks.io/python-data-structure-cn/3.%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/3.9.%E4%B8%AD%E7%BC%80%E5%89%8D%E7%BC%80%E5%92%8C%E5%90%8E%E7%BC%80%E8%A1%A8%E8%BE%BE%E5%BC%8F/ """ prec = {} prec["*"] = 3 prec["/"] = 3 prec["+"] = 2 prec["-"] = 2 prec["("] = 1 opStack = Stack() postfixList = [] tokenList = infixexpr.split() for token in tokenList: if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789": postfixList.append(token) elif token == '(': opStack.push(token) elif token == ')': topToken = opStack.pop() while topToken != '(': postfixList.append(topToken) topToken = opStack.pop() else: while (not opStack.isEmpty()) and (prec[opStack.peek()] >= prec[token]): postfixList.append(opStack.pop()) opStack.push(token) while not opStack.isEmpty(): postfixList.append(opStack.pop()) return " ".join(postfixList) def postfixEval(postfixExpr): """ 后缀表达式的算值 根据后缀表达式的特点,很容易可以想到,将运算数压入栈,当出现符号时,弹出栈顶两个元素,计算完成后压入栈, 等待下一个运算数或者运算符,最后栈顶元素就是后缀表达式的值。 """ operandStack = Stack() tokenList = postfixExpr.split() for token in tokenList: if token in "0123456789": operandStack.push(int(token)) else: operand2 = operandStack.pop() operand1 = operandStack.pop() result = doMath(token, operand1, operand2) operandStack.push(result) return operandStack.pop() def doMath(op, op1, op2): """ 后缀表达式运算值的辅助函数 输入三个参数(运算符,操作数1,操作数2),返回运算结果。 """ if op == "*": return op1 * op2 elif op == "/": return op1 / op2 elif op == "+": return op1 + op2 else: return op1 - op2 #栈的测试 # s= Stack() # print(s.isEmpty()) # s.push(4) # s.push('dog') # print(s.peek()) # s.push(True) # print(s.size()) # print(s.isEmpty()) # s.push(8.4) # print(s.pop()) # print(s.pop()) # print(s.size()) # 符号匹配的测试 # print(match_sympol('')) # 十进制数转二进制的测试 # print(ten2two(100)) # 中缀表达式转后缀表达式的测试 # print(infixToPostfix("( A + B ) * C - ( D - E ) * ( F + G )")) # 后缀表达式的求求值 # print(postfixEval('7 8 + 3 2 + /'))

正则表达式及re库的使用

Python [[Regular Expression]] 正则表达式及re库的使用 一、正则表达式 正则表达式要做的事简单地说就是字符串匹配,它由普通字符、非打印字符、特殊字符、限定符和定位符构成。理论上可以匹配一切字符串。 二、什么是正则表达式 正则表达式30分钟入门教程 正则表达式手册 三、在线正则表达式测试 regex101 在线正则表达式测试 三、常用的匹配规则 模式 描述 | 将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。串行“\”匹配“\”而“(”则匹配“(”。 ^ 匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。 $ 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。 * 匹配前面的子表达式零次或多次。例如,zo*能匹配“z”以及“zoo”。*等价于{0,}。 + 匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。 ? 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等价于{0,1}。 {n} n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。 {n,} n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。 {n,m} m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。 ? 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。 . 匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(. (pattern) 匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“\(”或“\)”。 (?:pattern) 匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。 (?=pattern) 正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 (?!pattern) 正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始 (?<=pattern) 反向肯定预查,与正向肯定预查类拟,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。 (?<!pattern) 反向否定预查,与正向否定预查类拟,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。 x|y 匹配x或y。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”则匹配“zood”或“food”。 [xyz] 字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。 [^xyz] 负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“p”。 [a-z] 字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。 [^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。 \b 匹配一个单词边界,也就是指单词和空格间的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。 \B 匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。 \cx 匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。 \d 匹配一个数字字符。等价于[0-9]。 \D 匹配一个非数字字符。等价于[^0-9]。 \f 匹配一个换页符。等价于\x0c和\cL。 \n 匹配一个换行符。等价于\x0a和\cJ。 \r 匹配一个回车符。等价于\x0d和\cM。 \s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。 \S 匹配任何非空白字符。等价于[^ \f\n\r\t\v]。 \t 匹配一个制表符。等价于\x09和\cI。 \v 匹配一个垂直制表符。等价于\x0b和\cK。 \w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。 \W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。 四、python 里的 re模块 4.1 match 这里首先介绍第一个常用的匹配方法 —— match,向它传入要匹配的字符串以及正则表达式,就可以检测这个正则表达式是否匹配字符串。 ...

硬 raid 快速配置

Linux RAID 硬 raid 快速配置 查看并清理 foreign configure /opt/MegaRAID/storcli/storcli64 /c0/fall show /opt/MegaRAID/storcli/storcli64 /c0/fall del 查看物理磁盘,确定数目和 eid 和 sid,一般是连续的 /opt/MegaRAID/storcli/storcli64 /c0/eall/sall show 配置 raid 一般需要确认 enclosure ID 和 Slot ID。 在这里 eid 就是 8,sid 就是 0-9 一共九块盘。根据第二步看到的数据进行修改。 /opt/MegaRAID/storcli/storcli64 /c0 add vd r5 size=all name=lotus drives=8:0-9 AWB ra direct strip=256 上述是一般 raid 创建,我们的存储机器有 36 块盘,所以指定前 18 块盘是一个 raid5,接着 17 块盘是一个 raid5,最后一个盘是全局热备盘。以 172.16.10.11 为例子: sudo /opt/MegaRAID/storcli/storcli64 /c0 add vd r5 size=all name=lotus drives=25:1-18 AWB ra direct strip=1024 sudo /opt/MegaRAID/storcli/storcli64 /c0 add vd r5 size=all name=lotus-2 drives=20:1-23 AWB ra direct strip=1024 sudo /opt/MegaRAID/storcli/storcli64 /c0/e26/s12 add hotsparedrive 根据实际需求,确定 eid 和 slot id,生成 raid,最后一步指定一个全局热备盘。 ...

硬盘接口-规范协议-传输总线

Hardware 硬盘接口 - 规范协议 - 传输总线 硬盘接口说明 硬盘对计算机总的来说,算是“外设”,具备容易扩展的特性,也拥有多种不同的接口。 IDE 接口 IDE 的英文全称为 “Integrated Drive Electronics”,即“电子集成驱动器”,它的本意是指把“硬盘控制器”与“盘体”集成在一起的硬盘驱动器。把盘体与控制器集成在一起的做法减少了硬盘接口的电缆数目与长度,数据传输的可靠性得到了增强。 不过 IDE 不仅指接口形式,主要还指硬盘的形式,即 IDE 硬盘,但人们习惯用 IDE 来统称 PATA 接口类的硬盘。 而 PATA 接口单纯指硬盘的接口形式,即“并行接口”。与之对应的是 SATA,即“串行接口”。其实 PATA 接口(并行接口)与 SATA(串行接口)的硬盘的严格上说都是IDE硬盘。如果说“PATA 接口的 IDE 硬盘"(简称 IDE 硬盘)和“SATA 接口的 IDE 硬盘”(简称 SATA 硬盘)会更准确点。 SATA 接口 使用 SATA(Serial ATA)口的硬盘又叫串口硬盘。Serial ATA 采用串行连接方式,串行 ATA 总线使用嵌入式时钟信号,具备了更强的纠错能力,与以往相比其最大的区别在于能对传输指令(不仅仅是数据)进行检查,如果发现错误会自动矫正,这在很大程度上提高了数据传输的可靠性。串行接口还具有结构简单、支持热插拔的优点。串口硬盘是一种完全不同于 PATA 的新型硬盘接口类型,由于采用串行方式传输数据而知名。相对于 PATA 来说,就具有非常多的优势。首先,Serial ATA 以连续串行的方式传送数据,一次只会传送 1 位数据。这样能减少 SATA 接口的针脚数目,使连接电缆数目变少,效率也会更高。(但 SATA 本质上是 SATA 接口的 IDE 硬盘。) SATA 3.0 能达到带宽 6Gb/s,速度 600MB/s。 ...

蓝鲸智云 5.1.29 搭建

Monitoring 蓝鲸智云 5.1.29 搭建 由于官方的安装指导文件更新于 2020-01-20,而 5.1.29 的安装包则是 2020-09-27 释出的,所以安装过程中会有坑,这里会对整个安装过程进行记录。 获取安装包并检验MD5码 axel https://bkopen-1252002024.file.myqcloud.com/ce/bkce_src-6.0.0.tgz -n 10 --output=/root/bkce_src-6.0.0.tgz md5sum /root/bkce_src-6.0.0.tgz 操作系统配置 1. yum 源更新 # centos7 为基准 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.cloud.tencent.com/repo/centos7_base.repo yum clean all yum makecache # centos7 epel mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup wget -O /etc/yum.repos.d/epel.repo http://mirrors.cloud.tencent.com/repo/epel-7.repo yum clean all yum makecache 2. 关闭 SELinux # 检查 SELinux 的状态,如果它已经禁用,可以跳过后面的命令 sestatus # 通过命令临时禁用 SELinux setenforce 0 # 或者修改配置文件 sed -i 's/^SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config reboot 3. 关闭默认防火墙(firewalld) # 检查默认防火墙状态,如果返回 not running,可以跳过后面的命令 firewall-cmd --state systemctl stop firewalld # 停止 firewalld systemctl disable firewalld # 禁用 firewall 开机启动 4. 安装 rsync 命令 # 检查是否有 rsync 命令,如果有返回 rsync 路径,可以跳过后面的命令 which rsync # 安装 rsync yum -y install rsync 5. 停止并禁用 NetWorkManager # 检查 NetworkManager 运行状态 systemctl status NetworkManager # 关闭并禁用 NetworkManager systemctl stop NetworkManager systemctl disable NetworkManager 6. 调整最大文件打开数 # 检查当前 root 账号下的 max open files 值 ulimit -n # 备份之前的配置文件 cp /etc/security/limits.conf /etc/security/limits.conf.bak # 增加配置信息 cat << EOF >> /etc/security/limits.conf root soft nofile 102400 root hard nofile 102400 EOF 7. 确认服务器时间同步 # 检查每台机器当前时间和时区是否一致,若相互之间差别大于3s(考虑批量执行时的时差),建议校时。 date -R # 查看和ntp server的时间差异(需要外网访问,如果内网有ntpd服务器,自行替换域名为该服务的地址) ntpdate -d cn.pool.ntp.org 如果输出的最后一行 offset 大于 1s 建议校时。 # 和 ntp 服务器同步时间 ntpdate cn.pool.ntp.org # 使用 ntpd 进行时间同步 http://xstarcd.github.io/wiki/sysadmin/ntpd.html 8. 检查 resolv.conf 是否有修改权限 检查 /etc/resolv.conf 是否被加密无法修改(即便是 root),执行如下命令,检查是否有“i”加密字样: ...

蓝鲸智云 v6.0.3 安装

Monitoring 蓝鲸智云 v6.0.3 安装 环境监测以及硬件配置 参考: 安装环境准备 脚本: curl -sSL http://172.16.0.219:8080/directlink/2/sh/sudo-2-firefly.sh|bash fdisk /dev/sda ==================================================================================================================== n t 31 w pvcreate /dev/sda1 vgcreate -s 32M data /dev/sda1 lvcreate -L 300G -n data00 data mkfs.ext4 /dev/data/data00 blkid |grep data ==================================================================================================================== echo 'UUID="26130f2b-ceb7-40d4-b1d9-8e2712735c55" /data ext4 defaults 0 0' >> /etc/fstab mkdir /data mount -a df -h wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.cloud.tencent.com/repo/centos7_base.repo yum clean all yum makecache wget -O /etc/yum.repos.d/epel.repo http://mirrors.cloud.tencent.com/repo/epel-7.repo yum clean all yum makecache systemctl disable firewalld yum -y install rsync pssh cat >> /etc/security/limits.conf << EOF root soft nofile 102400 root hard nofile 102400 EOF ntpdate cn.pool.ntp.org hostnamectl set-hostname tencent-bk1 timedatectl set-timezone Asia/Shanghai sed -i 's/^SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config reboot 获取安装包和证书文件 下载页 证书下载页 注意,证书需要三台节点的第一块网卡的mac地址,且下载证书是需要QQ登录的。 ...

译-终结一个进程和它的所有后代

Linux [译]终结一个进程和它的所有后代 终结一个类UNIX系统的进程可能比预期要复杂。上周我正在调试一个信号量停止工作导致的奇怪问题。更具体地说,涉及终结作业中正在运行的进程的问题。以下是我学到的内容的亮点: 类 UNIX 操作系统有很复杂的进程关系。父子进程、进程组、会话和会话负责人。但是,Linux 和 macOSX 等操作系统的细节并不统一。符合 POSIX 标准的操作系统支持向具有负 PID 编号的进程组发送信号。 在会话中向所有进程发送信号对于系统调用来说并不简单。 使用 exec 启动的子进程可以继承父进程的信号量信息。 杀死父进程不会杀死子进程 每个进程都有一个父进程,我们可以通过 pstree 或 ps 程序观察到这一点。 # start two dummy processes $ sleep 100 & $ sleep 101 & $ pstree -p init(1)-+ |-bash(29051)-+-pstree(29251) |-sleep(28919) `-sleep(28964) $ ps j -A PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 0 1 1 1 ? -1 Ss 0 0:03 /sbin/init 29051 1470 1470 29051 pts/2 2386 SN 1000 0:00 sleep 100 29051 1538 1538 29051 pts/2 2386 SN 1000 0:00 sleep 101 29051 2386 2386 29051 pts/2 2386 R+ 1000 0:00 ps j -A 1 29051 29051 29051 pts/2 2386 Ss 1000 0:00 -bash ps 命令显示 PID (进程的 ID)和 PPID (进程的父 ID)。 ...

超微主板更新 BIOS

Hardware 超微主板更新 BIOS 该操作本身已没有多少难度,相关教程一搜一大把,主要分以下几步。 下载 Refus(Windows平台)软件 下载 MS-DOS 镜像(建议从 i tell you 获取) 从超微官网找到对应主板最新的 BIOS 文件压缩包,下载流程可以参考 supermicro X10和X11主板或平台BIOS和BMC/IPMI固件更新 找到一个 U 盘,通过 Refus 软件,将第二步获得的镜像拷入 将第三步的压缩包解压,放到 U 盘剩余空间中 将 U 盘插入到待升级的主板上,进入 Bios,选择 UEFI:Build-in shell 的方式启动,之后的操作可以参考:超微主板BIOS固件更新图解 超微 X10DAi BIOS固件升级 主要难点在于,新生代的技术人员,已经很少接触 DOS,无法理解 DOS 到底该怎么用,所以在配置 DOS 引导盘的时候走了不少弯路。牵扯到底层的更新,DOS 还是更有效。

软 raid 配置简单操作

Linux RAID 软raid配置简单操作 分以下几步: 停止已有的md 磁盘分区 创建软raid虚拟磁盘 格式化磁盘 挂载磁盘 停止已有的md 通过 ls -al /dev/md*,观察是否已有 mdxxx 的字样,如果有则需要先清掉。 all_disk=`fdisk -l|grep '1.8 T'|awk '{print $2}'|cut -d":" -f1` part_disk=`fdisk -l|grep 'Linux raid autodetect'|awk '{print $1}'` umount /dev/md/cache md_list=`ls -al /dev/md/*|awk '{print $9}'` for i in $md_list do mdadm -S $i done mdadm --misc --zero-superblock $part_disk rm -f /etc/mdadm.conf rm -f /etc/mdadm/mdadmin.conf 磁盘分区 通过 fdisk -l,观察每块nvme磁盘是否都有一个分区,且该分区的类型是 Linux raid autodetect。如果不是则需要配置。 fdisk /dev/nvme?n1 # 下列操作需要依据需求来做,一般通过n创建分区,通过fd指定类型,通过w写入数据。 创建软raid虚拟磁盘 这一步不难,如果前面做好的话。 blkid $part_disk /sbin/mdadm --create cache --auto yes --level 0 -n`echo $part_disk|wc -w` $part_disk 上面的指令出现了五个问号,都是数字。其中n后面的数字是指一共几个磁盘,nvme后面的指盘符。 ...