Relative Content

K4NZDROID

category

「Bash」- shift(学习笔记)

命令语法格式
shift [n]
命令含义
从n+1开始的参数,被对应到$1,而由$#开始到$#-n+1代表的参数会被重置掉。换句简单的话说:shift后面的n是几,那前几个参数就不要了,假装你没有传过。
参数n必须为非负整数,并且小于等于$#;
如果没有指定n,则n默认为1;
如果n > $#,则位置参数不发生改变;
如果n = 0,则参数不会发生改变;
返回状态
如果n > $#,返回的状态值大于0,或者小于0;
正常情况、没有错误,则返回0。
示例

#!/bin/bash

function cmd(){

shift 2
echo $@
}

cmd 1 2 3 4 5 6 7 8
# 该命令输出:3 4 5 6 7 8
# 此时n=2,那前两个参数就不要了。[……]

READ MORE

「Bash」- type(学习笔记)

命令语法格式
type [-aftpP] name [name …]
命令支持的选项及含义
如果没有选项,type会输出每个做为命令的name将会被如何解释。
如下示例:

# type ls cd mkdir
ls is aliased to `ls -a -CF –color=auto’
cd is a shell builtin
mkdir is /bin/mkdir

-t 如果name是别名、shell保留字、函数、内建命令、普通文件(命令程序)则分别打印alias, keyword, function, builtin, file。 如果name没有找到则什么都不打印,且返回码为false。
如下示例:

# type -t ls
alias

# type -t mkdir
file

-p 如果作为命令名指定name,则type会返回会被执行的硬盘文件。 如果type -t name不返回file,则使用-p时什么都不输出。
示例如下:

# type -p readlink
/bin/readlink

# type -t ls
alias
# type -p ls

这里因为ls被定义成别名,所以使用-p时没有任何输出。

-P 即使type -t name没有返回file,也强制到PATH中搜索name。如果命令做了hash,-p与-P打印hash的值,不一定是第一个出现在PATH中的文件。
-a 使用该选项后将会打印所有命名为name的可执行命令。同时包含了别名和函数,但只有在没有使用-p选项的情况下。 当使用-a时,被hashed的命令不会进行输出。
示例如下:

# type -a ls
ls is aliased to `ls -a -CF –color=auto’
ls is /bin/ls

-f 使用该选项后,不查找shell中定义的函数。
命令返回值
如果type找到了命令,则返回true; 如果type没有找到命令,则返false;[……]

READ MORE

「Bash」- umask

命令语法格式
umask [-p] [-S] [mode]
命令简述
设置创建文件时权限的默认掩码。
命令支持的选项及含义
如果没有指定mode,则打印当前的掩码值。
[mode] 权限的掩码。如果mode以数字开头,则被解释为八进制的掩码数字。否则,mode被当作可由chmod(1)接受的符号模式掩码进行解释。
以下的两种示例格式都是合法的:

# umask 022
# umask u=rwx,g=rx,o=rx

但是,umask 022中的022设置的是权限的掩码,而umask u=rwx,g=rx,o=rx中的u=rwx,g=rx,o=rx设置的是默认的权限。
-S 默认不使用-S时,以八进制格式打印掩码值;使用-S后以符号的形式打印出掩码值。
如下示例:

# umask
0022

# umask -S
u=rwx,g=rx,o=rx

-p 如果使用了-p选项,并且没有指定mode,则以可重用为输入的形式进行输出。
如下示例:

# umask -p
umask 0022

# umask -p 022

对于命令umask -p 022没有任何的输出。
命令的返回值
如果mode修改成功或者没有提供参数,则返回0;其他情况返回false;[……]

READ MORE

「Shell」- 处理 JSON 数据

问题描述
我们需要在 Shell 中处理 JSON 数据,比如我们请求某个 HTTP 接口,接口返回 JSON 数据,而我们需要从中提取某个字段。当然,我们可以使用 sed grep awk 这些工具,但是这些工具只能进行简单处理。如果我们想要生成结构化数据,这些工具是不够的。我们需要处理 JSON 的专用工具。
经过 Google 查找 jq(stedolan/jq: Command-line JSON processor),用于处理 JSON 数据的 Shell 命令行工具。
该笔记将记录:在 Shell 中,如何使用 jq 命令处理 JSON 数据,以及常见问题处理。
解决方案
安装命令
通过包管理器安装。很多 Linux 发行版中都带有该工具:

# Ubuntu 18.04 LTS
apt-get install -y jq

或者,使用源码编译安装,详细的安装过程,参考 jq/README.md at master · stedolan/jq 文件。这里简单记录:

git submodule update –init # if building from git to get oniguruma (正则表达式库)
autoreconf -fi # if building from git
./configure –with-oniguruma=builtin
make -j8
make check

常见示例
根据属性值过滤:

jq ‘.result | select(.location==”Stockholm”)’

判断某个 KEY 是否存在。比如,判断在 result 是否包含 .property_history 字段(KEY),存在则取其值:

jq ‘.result | select(.property_history != null) | .property_history’

判断字段的值是否以某个字符串开始:

jq -r ‘.[]|select(.hostname | startswith(“abcd”))’ jjjj.json

# 判断是否包含某个字符串
jq -r ‘.[]|select(.hostname | contains(“abcd”))’ jjjj.json

修改 JSON 内容:

jq ‘.clusters[].name = 1231231 | .users[].name = 123456’ config.js[……]

READ MORE

「Shell」- 进程替换(Process substitution)

什么是进程替换
先看 WIKI 的解释:

In computing, process substitution is a form of inter-process communication that allows the input or output of a command to appear as a file.

在计算中,进程替换是进程间通信的一种形式,允许命令的输入或输出作为文件出现;

进程替换的语法
cmd1 >(cmd2)

将 cmd1 输出发送给 cmd2

cmd1 <(cmd2)

将 cmd2 的输出发送给 cmd1

在这里:>(cmd2)或者<(cmd2)等价于一个内容为 cmd2 输出的文件。这么说可能不明白,请看下面“进程替换的机制”;
进程替换的机制
题外话: 如果你不会英语,你真的会错过很多东西;
进程替换的实现有两种:

在支持 /dev/fd 的系统上(大多数都支持),通过 pipe()系统调用实现。pipe()系统调用会为匿名管道返回一个文件描述符$fd,然后用字符串 /dev/fd/$fd 替换命令行上的>(cmd2)或者<(cmd2);
对于不支持 /dev/fd 的系统上,Bash 使用新临时文件名调用 mkfifo 来创建一个命名管道,然后使用此文件名作为替代;

为了演示所涉及的步骤,思考如下命令:

diff file1 <(sort file2)

shell 的执行步骤如下(对于支持 /dev/fd 的系统):

创建一个新的匿名管道。这个管道可以通过像 /dev/fd/63 这样的东西访问;你可以用echo <(true)命令看到它;
在后台执行替代命令(当前为 sort file2),将输出输送到匿名管道;
执行主命令,使用匿名管道的路径替换替带命令。在这个例子中,完整的命令可能扩展为:diff file1 /dev/fd/63
当执行结束时,关闭匿名管道;

对于命名管道(不支持 /dev/fd 的系统),唯一不同的地方在于管道的创建和删除:使用 mkfifo 创建;使用 unlink 删除。其他方面一样的;
进程替换的示例

#!/bin/sh

echo <(ls)

# 输出:
# /dev/fd/63

对于cmd1 >(cmd2),当 Bash 在执行进程替换的时候,Bash 会将 cmd2 的[……]

READ MORE

「Shell」- 处理 YAML 文件

yq (GitHub/kislyuk/yq) ⇒ Python
项目地址:kislyuk/yq: Command-line YAML and XML processor – jq wrapper for YAML/XML documents 官方文档:https://kislyuk.github.io/yq/
YAML ⇒ JSON,用于将 YAML 转为 JSON 的工具。该工具是 jq 的封装,所以需要先安装 jq 命令
安装 yq 命令: 1)安装 jq 命令:jq 2)安装 yq 命令:

pip3 install yq

yq (GitHub/mikefarah/yq) ⇒ Go
项目地址:mikefarah/yq: yq is a portable command-line YAML processor
YAML ⇒ JSON,用于将 YAML 转为 JSON 的工具,由 Go 语言开发。
我们没有使用该命令,这里仅作记录。
常用工具
yamllint – A linter for YAML files
该工具用于检查YAML文件的格式是否正确,对YAML进行校验。
执行如下命令即可安装该工具:

# CentOS:
yum install yamllint.noarch

# Debian
apt-get install yamllint

简单的使用示例:

yamllint /path/to/foo.yml

其他内容可以 查看GitHub项目主页、查看命令手册[……]

READ MORE

「Shell」- 常用代码

explainshell.com
解释 Shell 命令的网站; 该站点的源码在 GitHub 中:https://github.com/idank/explainshell
将 Unicode 与 Ascii 互相转化
使用 ascii2uni 和 uni2ascii 在 Unicode 和 Ascii 之间互转;
使用 printf 也可以做到;
执行生成的命令
scripting – Bash: Execute piped lines from stdin – Server Fault
我们会通过 Shell 脚本来生成一些命令,然后再执行这些命令:python example.py | bash
或,更具数据直接组装并执行命令,但有时候这种做法更烦琐;
输入特殊字符
比如输入一个 TAB 键,但是 Bash 中 TAB 用于补全提示。。;
先按下 Ctrl+V,然后在按下 TAB 键;
当 BASH 无响应时
使用 Ctrl+J 组合键;或者输入 reset 内建命令;
修改运行进程的输出
「redirecting output of running background job in bash」 「How to redirect output of an already running process」
脚本优化
Bash script; optimization of processing speed
“The first rule of optimization is: don’t optimize.”
如果数据量大的话还是要换语言(当然,这要你自己控制成本、时间、性能上的平衡)。
倒是有些通用的小办法,可以参考「Bash script; optimization of processing speed」一文中的说明。
你可以自己优化程序,但是你要防止“在优化后,逻辑不如原来清晰、直接”的问题。
参考文献
Read the json data in shell script How to convert \uXXXX unicode to UTF-8 using console tools in *nix[……]

READ MORE

「Shell」- 数组的使用

注意事项
并不是每种 Shell 都支持数组(比如 Bash 支持数组,但是 Dash 不支持数组),为了写出可移植脚本,不建议使用数组。
The Bourne shell or the Unix sh lanuage specification don’t support arrays.
定义 – 如何定义一个数组?
索引数组

# 声明索引数组
declare -a mIndexArray

# 索引数组也可以直接定义:
mIndexArray=(one two three)

关联数组

# 声明关联数组
declare -A mAssociativeArray

# 但是,关联数组不可以直接定义,必须先声明:
declare -A mAssociativeArray
mAssociativeArray=( [foo]=bar [baz]=quux [corge]=grault )

# 如果没有先声明为关联数组,则 mAssociativeArray=( [foo]=bar [baz]=quux [corge]=grault ) 默认为索引数组,并且其中的元素也发生了变化。

赋值 – 如何对数组进行赋值?
对索引数组和关联数组进行赋值方面,两者直接并无太大差异:

mIndexArray[5]=five
mAssociativeArray[five]=five

数组索引也可以是变量:

mAssociativeArray[$var]=value

即使索引是“存在空格的字符串”,也不需要引用:

# 下面三种是等价的
mAssociativeArray[‘key with space’]=value
mAssociativeArray[“key with space”]=value
mAssociativeArray[key with space]=value

也可以使用如下方式,以无需索引的方式向数组中添加元素:

# 如下示例向索引数组mIndexArray中添加了两个元素,但是无需指定索引
mIndexArray=()
mIndexArray+=(‘foo’)
mIndexArray+=(‘bar’)

取值 – 如何取值及打印整个数组?
从数组中取值
对索引数组和关联数组进行取值方面,两者直接并无太大差异:

echo ${mIndexArray[5]}
echo ${mAssociativeArray[five]}
echo ${mArray[$var]}
ehco ${mArray[var with space]}

打印整个数组[……]

READ MORE

「Shell」- 从数组中,随机选择元素

问题描述
在多数高级语言中,从数组或列表中随机获取元素是很常见的事情。那么在 Shell 中,也不例外,我们也会遇到需要从数组中随机获取元素的需求。
该笔记将记录:在 Shell 中,如何从数组中随机获取元素。
注意事项
并不是每种 Shell 都支持数组,例如 Bash 支持数组,但是 Bourne Shell (sh) 并不支持数组。我们希望可以写出可移植性高的代码,因此我们不会针对特定 Shell 来编写代码。该笔记也将记录更加通用的方法(但是,代码可能会比较难看)。
如果我们的需求复杂、数组复杂,我们会使用 Python Perl 脚本来处理,而不会使用 Shell 处理。
适用于 Bourne shell 的脚本
# 08/04/2020

#!/bin/sh

list=”aes aes-128 aes-192 salsa20 blowfish twofish cast5 3des tea xtea xor sm4″
set — $list
shift $(expr $RANDOM % $#)
KCPTUN_CRYPT=”$1″

echo $KCPTUN_CRYPT

set:将 $list 的值作为当前 Shell 参数,就好像在执行脚本时传入这些参数; shift:“洗牌”。由于参数是不确定的,所以没人知道第一个参数将是谁,也就是我们要获取的参数;
# 02/15/2021

#!/bin/sh

a=”\
111111111111111111111111111111F\n
2222222222222222222222222222222\n
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n
ccccccccccccccccccccccccccccccc\n
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF”

count=$(echo -e $a | wc -l) # 行数
random_line_number=$(expr “${RANDOM}” % “${count}” + 1) # 目标行号
random_line=$(echo -e $a | awk ‘NR==’${random_line_number}’ {print;exit}’) # 读取该行

echo $random_line

参考文献
linux – Arrays in Shell Script, not Bash – Stack Overflow[……]

READ MORE

「Shell」- 文件及路径

获取当前脚本路径

SCRIPT_PATH=$(readlink -f “$0”) # 获取脚本的绝对路径
SCRIPT_FOLDER=$(dirname “$SCRIPT_PATH”) # 从绝对路径中获取脚本所在目录
echo $SCRIPT_FOLDER

该方法适用于软链接情况:即使执行的时只向脚本的软链接,此方法依旧可以获取脚本的绝对路径,而不是软链接的路径;
删除指定目录以外的目录
Remove all files except some from a directory

shopt -s extglob
rm !(textfile.txt|backup.tar.gz|script.php|database.sql|info.txt)

文件或目录查找
获取某个目录下的 Git 仓库

# 这招是从 OpenJDK 的源码中学的:「make/scripts/hgforest.sh」
ls -d ./.git ./*/.git ./*/*/.git ./*/*/*/.git ./*/*/*/*/.git 2>/dev/null

参考文献
Unix shell script find out which directory the script file resides? – Stack Overflow[……]

READ MORE

「Shell」- 在使用 Sudo 命令时,向文件中插入内容

问题描述
当使用 sudo 命令时,如果向文件中重定向内容,将产生 Permission denied 错误:

$ sudo -u root cat >> /root/.ssh/authorized_keys2 <<EOF
ssh-rsa xxxxxxxxxxxx
EOF
-bash: /root/.ssh/authorized_keys2: Permission denied

问题原因
重定向(>>)是由当前 Shell 执行的,它需要先打开文件。但是,当前 Shell 没有权限打开 authorized_keys2 文件,因此产生错误。
解释说明:重定向(>>)不是 Shell 命令,而是 Shell “符号”。当 Shell 收到命令后,需要先进行处理。如上命令,当前 Shell 需要先打开 authorized_keys2 文件,然后在 cat 输出后,将输出写入文件。(如果难以理解,可以反过来想:如果 Shell 不处理 >> 符号,那么该符号就要传递到命令中,由特定命令来处理,也就是说每个命令都要处理 >> 符号,才能实现重定向功能。很显然,这有可能,但不合理)
解决方案

echo ‘ssh-rsa xxxxxxxxxxxx’ | sudo tee -a /root/.ssh/authorized_keys2

在命令中,通过管道将内容写入文件。管道符号(|)也是由 Shell 处理的,但是管道与重定向是两种完全不同的方法。在 C 中,需要从 stdin 中读取管道数据。
参考文献
permissions – How to insert text into a root-owned file using sudo? – Unix & Linux Stack Exchange stdin – How to read piped content in C? – Stack Overflow[……]

READ MORE

「Shell」- 常用字符串操作(String)

字符串 => 字符数组
Bash: Split string into character array

echo “abcdefg” | fold -w1

echo “abcdefg” | grep -E -o .

大小写转换
How to convert a string to lower case in Bash?
字符串重复(repeat)
How can I repeat a character How do I find the width & height of a terminal window?
要在终端里打印一条分隔线,这条分隔线由”#“组成,宽度与终端的宽度相同;

# 问题一、如何重复字符串?
printf ‘#%.0s’ {1..100}

# 问题二、如何获取终端的宽度?
tput cols

# 合并后的代码
# 可能你需要在结尾加上一个换行符,默认 printf 是不带换行符的
printf ‘#%.0s’ $(seq $(tput cols))

urldecode
bash – How to decode URL-encoded string in shell? – Stack Overflow
在 Bash 中,进行 urldecode 的方法,以及相关问题处理。
这段代码从 Stack Overflow 复制而来

function urldecode() { : “${*//+/ }”; echo -e “${_//%/\\x}”; }

function urldecode() { local i=”${*//+/ }”; echo -e “${i//%/\\x}”; }

第一个写法太奇怪了,里面包含各种 Bash 知识: 1): 是为了防止 “${*//+/ }” 被当作命令来执行 2)$_ 表示前个命令的最后一个参数,也就是 “${*//+/ }” 的解析结果 3)$* 表示传入命令的全部参数 4)${p/+/ } 表示将变量 p 的 + 替换为空格,而 ${p//+/ } 表示将变量 p 的全部 + 替换为空格;[……]

READ MORE

「Shell」- 判断字符串结尾

下面围绕“判断字符串是否以.txt 结尾”展开。转变一下也同样适用于“判断字符串是否以.txt 开头”;
通用方法
方法一、使用 grep 命令

str=”/path/to/foo.txt”

# 使用 if 语句
if echo “$str” | grep -q -E ‘\.txt$’
then
echo “true”
else
echo “false”
fi

# 写成一行
echo “$str” | grep -q -E ‘\.txt$’ && echo true || echo false
grep -q -E ‘\.txt$’ <<< “$str” && echo true || echo false

方法二、使用 expr 命令

str=”/path/to/foo.txt”

# 使用 if 语句
if expr “$str” : ‘.*\.txt$’ &>/dev/null
then
echo “true”
else
echo “false”
fi

# 写成一行
expr “$str” : ‘.*\.txt$’ &>/dev/null && echo true || echo false

方法三、使用 case 指令

str=”/path/to/foo.txt”

case “$str” in
*.txt ) echo “true”;;
* ) echo “false”;;
esac

其他方法
还可以使用 AWK、SED 命令,这里就不再介绍了,方法和上面是类似的;
特定方法
BASH

# BASH 中的正则表达式
[[ “/path/to/foo.txt” =~ .*txt$ ]] && echo “true” || echo “false”

# BASH 的特殊语法
[[ “/path/to/foo.txt” = *txt ]] && echo “true” || echo “false”

参考文献
How do I do if(string.endsWith(“/”)) in shell Bash String Comparison: Find Out IF a Variable Contains a Substring[……]

READ MORE

「Shell」- 常见错误汇总

内容简介
本部分整理了Shell中的常见错误,包括脚本错误,命令错误等等。
-bash: /dev/null: Permission denied
-bash: /dev/null: Permission denied – Unix & Linux Stack Exchange
问题描述:在 Linux 中,当登录系统时,提示 /dev/null: Permission denied 消息
问题原因:多半是有人把 /dev/null 改变为常规文件;
解决方法:1)重启操作系统,2)或者,重新创建 /dev/null 文件:

rm -f /dev/null; mknod -m 666 /dev/null c 1 3[……]

READ MORE

「XML」- 可扩展标记语言(Extensible Markup Language)

XML(Extensible Markup Language,可扩展标记语言),被设计用来传输和存储数据。
XML 文档形成了一种树结构,从根开始展开。

<?xml version=”1.0″ encoding=”UTF-8″?>
<note>
<to>Learners</to>
<from>Huawei</from>
<heading>Reminder</heading>
<body>Don’t forget Reading!</body>
</note>

文件头
<?xml version=”1.0″ encoding=”UTF-8″?> 其中: 1)<?:表示一条指令的开始。 2)xml:表示此文件是XML文件。 3)version:XML版本号。”1.0″表示使用XML1.0标准版本。 4)encoding:字符集编码格式,当前仅支持UTF-8编码。 5)?>:表示一条指令的结束。
标签
标签 <note>、<to>、<from>、<heading>、<body> 为私有。XML语言没有预定义的标签,允许使用者自定义标签和文档结构。 标签格式嵌套内容。“/”表示结束当前标签。
参考文献
Wikipedia/XML[……]

READ MORE

「DTD」- Document Type Definition

DTD是什么?
文档类型定义(DTD)是“标记声明”的一个集合,用于定义SGML系列标记语言(SGML,XML,HTML)的“文档类型”。
DTD定义XML文档的结构、合法元素、属性。
简单的说:一个DTD文件描述了一个XML文件的结构。
为什么使用DTD?
通过 DTD,您的每一个XML文件均可携带一个有关其自身格式的描述。(规定XML结构)
通过 DTD,不同的组织可以一致地使用某个标准的DTD来交换数据。(规范数据结构)
而您的应用程序也可使用某个标准的DTD来验证从外部接收到的数据。(数据结构合法性检查)
如何使用DTD?
DTD用于定义XML的结构,它可以在XML文档中声明(“内联声明”),也可以引入XML文档(“外部引用声明”)。
内联声明

<?xml version=”1.0″?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don’t forget the meeting!</body>
</note>

外部引用声明
外部引用声明是将DTD与XML分离,因此需要定义两个文件:
用于定义的note.dtd文件:

<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>

包含数据的note.xml文件:

<?xml version=”1.0″?>
<!DOCTYPE note SYSTEM “note.dtd”>
<note>
<to>George</to>
<fr[……]

READ MORE

「XSL」- Extensible Stylesheet Language

XSL
可描述如何来显示 XML 文档!
XSLT
一种用于转换 XML 文档的语言;
XPath
一种用于在 XML 文档中导航的语言;
XSL-FO
一种用于格式化 XML 文档的语言;
示例内容
#1 cdcatalog.xml

<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<!– Edited with XML Spy v2007 (http://www.altova.com) –>
<?xml-stylesheet type=”text/xsl” href=”cdcatalog.xsl”?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>When a man loves a woman</title>
<artist>Percy Sledge</artist>
<country>USA</country>
<company>Atlantic</company>
<price>8.70</price>
<year>1987</year>
</cd>
<cd>
<title>Unchain my heart</title>
<artist>Joe Cocker</artist>
<country>USA</country>
<company>EMI</company>
<price>8.20</price>
<year>1987</year>
</cd>
</catalog>

#2 cdcatalog.xsl

<?xml version=”1.0″ encoding=[……]

READ MORE

「Nginx」- 当 autoindex on; 时,修改输出页面的格式

XSLT是什么?

使用示例
在 Nginx 的 autoindex_format xml 中,产生类似如下的输入:

<?xml version=”1.0″?>
<list>
<directory mtime=”2018-02-08T01:31:45Z”>keyboard</directory>
<directory mtime=”2018-02-08T01:31:54Z”>make</directory>
<directory mtime=”2018-02-13T06:30:57Z”>mysql</directory>
<directory mtime=”2018-08-07T07:55:17Z”>shell</directory>
<directory mtime=”2018-02-08T01:40:09Z”>vbscript</directory>
<directory mtime=”2017-04-05T09:50:39Z”>website</directory>
<file mtime=”2017-04-06T01:52:35Z” size=”1280498″>Bv9ARM.pdf</file>
<file mtime=”2016-10-19T03:34:22Z” size=”489747″>IHI0044F_aaelf.pdf</file>
<file mtime=”2016-10-19T03:34:41Z” size=”102925150″>LinuxCMDAndShellScripts.pdf</file>
</list>

相关教程
w3schools.com/XSLT Introduction W3school/XSLT 教程
参考文献
Wikipedia/XSLT[……]

READ MORE

「XML」- 杂记

操纵工具
XMLStarlet
可以用xmlstarlet命令从命令行中修改XML文件。也是在修改libvirt的域定义文件时遇到的需求,那时候我有一堆的XML文件要修改……
对于如下XML内容:

<root>
<node user=”user1″>
<tag k=”name” v=”name1″/>
</node>
<node user=”user2″>
<tag k=”network” v=”nw1″/>
</node>
<node user=”user3″>
<tag k=”foo” v=”bar”/>
</node>
</root>

如果向删除第一个<node>节点:

<node user=”user1″>
<tag k=”name” v=”name1″/>
</node>

可以执行xmlstarlet ed -d ‘//root/node[tag[@v=”name1″]]’ /path/to/file.xml命令,修改后的内容会写入标准输出。如果想写入文件,可以使用-L, –inplace选项,即xmlstarlet ed -L -d ‘//root/node[tag[@v=”name1″]]’ /path/to/file.xml命令。
参考文献 Remove XML Nodes using Unix Command Line Start working with XMLStarlet
xsltproc
这个也可以,不过好像挺复杂的,没深入研究。
参考文献
Edit xml file using shell script / command[……]

READ MORE

「NAT」- Network Address Translation(网络地址转换)

问题描述
随着互联网发展和网络应用的增多,IPv4 地址枯竭已经成为制约网络发展的瓶颈; 随着互联网用户的增多,IPv4 的公有地址资源显得越发短缺; 同时 IPv4 公有地址资源存在地址分配不均的问题,这导致部分地区的 IPv4 可用公有地址严重不足; 为解决该问题,使用过渡技术解决 IPv4 公有地址短缺就显得尤为必要;
解决方案
NAT(Network Address Translation,网络地址转换)是 1994 年提出的。当在专用网内部的一些主机本来已经分配到了本地 IP 地址(即仅在本专用网内使用的专用地址),但又想和因特网上的主机通信(并不需要加密)时,可使用 NAT;
NAT,主要用于实现位于内部网络的主机访问外部网络的功能。当局域网内的主机需要访问外部网络时,通过 NAT 技术能够将其私网地址转换为公网地址,并且多个私网用户能够共用同个公网地址,这样既可保证网络互通,又节省了公网地址;
尽管 IPv6 可以从根本上解决 IPv4 地址空间不足的问题,但目前众多的网络设备和网络应用仍是基于 IPv4 的,迁移将带来大量的工作。因此在 IPv6 广泛应用之前,这种过渡技术的使用是解决地址短缺的主要技术手段;
原理简述
NAT,网络地址转换,对 IP 数据报文中的 IP 地址进行转换,是一种在现网中被广泛部署的技术。NAT 将重写数据包中的源地址或目的地址,用于解决地址短缺的问题。它的主要原理是,在网络中的多台主机,通过共享同个公网地址来访问外网资源。同时,由于 NAT 屏蔽了内网网络,自然也就为局域网中的机器提供了安全隔离;

NAT 的典型应用场景:在私有网络内部(园区、家庭)使用私有地址,出口设备部署 NAT 技术: 1)对于“从内到外”的流量,网络设备通过 NAT 将数据包的 SRC-ADDRESS 进行转换(转换成特定的公有地址), 2)对于“从外到内”的流量,则对数据包的 DST-ADDRESS 进行转换;
通过私有地址的使用结合 NAT 技术,可以有效节约公网 IPv4 地址;
NAT映射条目由首包触发,当一段时间没有流量时,为了安全考虑NAT映射条目自动删除。
特性特征
私网地址与公网地址,一对一映射;
NAT 不仅能解决了 lP 地址不足的问题,
而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机;
应用场景

企业或家庭使用私有网络,使用私有地址;运营商使用公共网络,使用公有地址;
NAT 一般部署在连接内网和外网的网关设备上;,例如路由器或防火墙上;
报文格式
将源地址或目的地址进行转换,也涉及源端口和目的端口的转换;
NAT 是种技术,而非协议,所以无[……]

READ MORE

「NAT」- 安全隐患

问题描述
数据通过 NAT 设备后,NAT 设备会建立 NAT 映射表。当 NAT 设备收到回程报文后根据映射表决定是否是合法回程报文,然后决定是否进行转发;

如果外部主机以 NAT 映射表中的公网 IP+Port 为目标发送数据,数据是否会被转发?—— 数据是会被转发的,原因在于 NAT 并不强制检查源地址,即针对源地址的检查是可选的;
解决方案
WIP
Tuple
内部 Tuple:内部主机的私有地址和端口号所构成的二元组,即内部主机所发送报文的源地址、端口所构成的二元组;
外部 Tuple:内部 Tuple 经过 NAT 的源地址 / 端口转换之后,所获得的外部地址、端口所构成的二元组,即外部主机收到经 NAT 转换之后的报文时,所看到的该报文的源地址和源端口;
目标 Tuple:外部主机的地址、端口所构成的二元组,即内部主机所发送报文的目标地址、端口所构成的二元组;

安全类型
NAT 可以分成两大类:Cone NAT(圆锥型 NAT)与 Symmetric NAT(对称型 NAT);
Cone NAT 又可以分为 Full Cone NAT(完全圆锥型)、Restricted Cone NAT(限制圆锥型)、Port -Restricted Cone NAT(端口限制圆锥型);
NAT 有 4 种不同的类型:
Full Cone NAT
Full Cone NAT(完全圆锥型):同一内部 Tuple 请求被 NAT 转换至同一外部 Tuple,任意外部主机就都能以外部 Tuple 中的地址和端口为目标发送报文,NAT 设备对收到的报文能正确转发。Full Cone NAT 处理方法简单,但安全性有缺陷;

内网 PC1 与 Web 服务器通信以后,NAT 设备生成 NAT 映射表,如果是 Full Cone NAT 类型,则攻击者以外部 Tuple(122.1.2.2:1025)为目标发送数据,则数据会被发送给 PC1;
Restricted Cone NAT
Restricted Cone NAT(限制圆锥型):Full Cone NAT 的受限版本,于 Full Cone NAT 概念类似,主要区别是 NAT 设备收到外部主机的报文时,除了查看报文目的地址+端口是否与外部 Tuple 一致外,还会查看报文源 IP 是否与目标 Tuple 中的 IP 地址一致,如果都一致则转发;

内网 PC1 与 Web 服务器通信以后,NAT 设备生成 NAT 映射表,如果是 Restricted Cone NAT 类型,则攻击者需要以外部 Tuple(122.1.2.2:1025)为目标地址+端口,以目[……]

READ MORE

「NAT」- 路由发布

问题描述
某些情况下 NAT 设备不一定是出口设备,因此需要将回程的流量引导至 NAT 设备上,
解决方案
此时可以在路由协议中引入 UNR 路由的方式解决问题;
UNR(User Network Route,用户网络路由),UNR 是非接口 IP 产生的路由,不存在于任何接口上。NAT 场景中,设备会为 NAT 地址池中的地址创建 UNR 主机路由。比如 NAT 地址池中有地址 122.1.2.2 和 122.1.2.3,则设备会自动创建 122.1.2.2/32 和 122.1.2.3/32 UNR 路由;[……]

READ MORE

「NETWORKING」- 智能选路

问题描述
云计算时代,网络的可靠性不再满足用户的需求,用户希望能够基于应用了解现网的情况,并根据应用的现状调整网络;
该需求对于原有的网络提出了挑战: 1)传统的网络无法很好地识别应用; 2)传统的网络无法基于应用调整;
解决方案
为了应对以上挑战,产生了两种技术: 1)SAC(Smart Application Control,智能应用控制),该技术能够灵活地识别应用; 2)SPR(Smart Policy Routing,智能策略路由),该技术能够基于网络的状况或者应用的状况切换转发路径;
原理简述
基于 SAC 识别应用,并通过 SPR 选路就可以保障特定业务在网络上的可靠性:

1)SAC 通过 SA 特征库与 FPI 特征库识别应用并分组流量; 2)SPR 基于探测报文确定链路质量从而决定转发路径;[……]

READ MORE

「NETWORKING」- 业务可靠性:智能应用控制,SAC,Smart Application Control

问题描述
传统网络主要是以流量为维度管理网络,但在云计算时代,业务变得原来越重要,网络不能再只基于过去的五元组管理网络,而需要以应用为维度管理监控网络;
一般的路由交换设备没有办法识别应用层的信息,以应用为维度管理网络存在较大难度;
解决方案
SAC(Smart Application Control,智能应用控制)技术能够帮助路由交换设备识别分类应用;
SAC 指利用 SA(Service Awareness,业务感知技术)和 FPI(First Packet Identification,首包识别技术),对报文中的第 4~7 层内容(如 HTTP、RTP)进行检测和识别;
原理简述
SAC 应用识别流程

当一条流量的报文进入设备之后,设备首先根据报文中携带的五元组信息,判断该报文是否已经识别过应用;
如果识别过,则不需要重复识别,直接将报文送入三层转发;
如果没有识别过,则送入 SAC 进行应用识别,依次查看 FPI 特征库和 SA 特征库;
SAC 识别结束后,报文根据 SAC 的识别结果进行业务处理,处理结束后送入三层转发;
其中,SAC 的识别流程为:先根据 FPI 中的 ACL 规则来识别应用;如果识别失败,再根据 FPI 中的 DNS 关联表来识别应用;如果识别失败,再根据 FPI 中的协议端口表来识别应用;如果三者都没有识别出应用,再送入 SA 继续识别;
SAC 特征库
特征识别是业务感知技术(SA)的最基本功能。不同的应用程序通常会采用不同的协议,而不同的应用协议具有各自的特征,能标识该协议的特征称为特征码。系统对流经设备的业务流进行分析,将分析结果和设备上的特征库进行对比,通过匹配数据报文中的特征码来识别出应用程序;
SAC 特征库包含: 1)FPI 特征库:FPI 的特征码是指可以用于 FPI 应用识别的特征码, 2)SA 特征库:SA 的特征码是指可以用于 SA 应用识别的特征码;
SAC 特征库文件只能以升级的方式进行更新,不可以手动修改;
SAC 特征库的升级方式有: 在线升级:可通过安全中心平台或者内网升级服务器升级 SAC 特征库 本地升级:通过安全中心平台下载升级包,通过 FTP 上传到设备本地,并进行升级;
SA(Service Awareness,业务感知)
当设备接收数据后,可以使用 SA(Service Awareness,业务感知)技术匹配应用;
SA 使用 SA 特征库感知业务,现有的 SA 特征库内置了 6000+应用,对于公有应用有非常高的识别率。SA 特征库一般不能手工修改,只能通过在线或本地升级更新 SA 特征库;

FPI
通过 SA[……]

READ MORE

「NETWORKING」- 业务可靠性:SPR(Smart Policy Routing,智能策略路由)

问题描述
云计算时代,越来越多的用户把关注点从网络的连通性转移到业务的可用性上,如业务的可获得性、响应速度和业务质量等。但是传统网络无法感知链路的质量和业务的需求,导致用户的业务体验较差;
解决方案
SPR(Smart Policy Routing,智能策略路由)就是在这一背景下产生的一种策略路由。它可以主动探测链路质量并匹配业务的需求,从而选择一条最优链路转发业务数据,可以有效地避免网络黑洞、网络震荡等问题;
原理简述

SPR 业务区分
SPR 可以根据协议类型,报文应用,报文信息区分不同流量;
不同业务可以设置不同的链路质量参数阈值,可以设置: 1)时延 D(Delay); 2)抖动时间 J(Jitter); 3)丢包率 L(Loss) 4)综合度量指标 CMI(Composite Measure Indicator):CMI 是基于时延,抖动,丢包综合计算得到的指标;
SPR 选路主要基于 CMI 值;

SPR 支持通过以下属性对业务进行区分: 根据协议类型区分:IP,TCP,UDP,GRE,IGMP,IPINIP,OSPF,ICMP; 根据报文应用区分:DSCP,TOS,IP Precedence,Fragment,VPN,TCP-flag; 根据报文信息区分:SRC-IP-ADDR,DST-IP-ADDR,Protocol,SRC-Port,DST-Port,SRC-IP-Prefix,DST-IP-Prefix;
SPR 根据 NQA 探测结果进行业务选路时, CMI 值的计算公式:CMI=9000 – cmi-method,其中 cmi-method 缺省定义为:D+J+L 使用 NQA 探测,CMI 值越大越优
SPR 根据 IP FPM 探测结果进行业务选路时, CMI 值的计算公式:CMI=D+J+L 使用 IP FPM 探测,CMI 值越小越优
SPR 探测链路和链路组
探测链路通过探针(NQA, IP FPM)获取链路参数的质量,SPR 根据探测链路的链路质量匹配业务需求,从而实现智能选路的需求;
SPR 以链路组的形式使用探测链路,一个链路组中可以有一条或多条探测链路;
SPR 的链路角色分为: 1)主用链路组 2)备用链路组 3)逃生链路。在 SPR 中,当业务无法从主用链路组和备用链路组中找到合适的链路传输数据时可以启用逃生链路;

SPR 业务选路
SPR 会定期获取 NQA 或 IP FPM 的探测结果,判断链路是否满足业务需求,如果不满足则触发链路切换;
SPR 业务选路过程如下:
1)根据 NQA 探测结果进行业务选路:
2)根据 IP FPM[……]

READ MORE

「GRE」- Generic Routing Encapsulation(通用路由封装协议)

问题描述
随着企业的发展,越来越多的企业需要在分支-总部之间进行内网通信。传统分支-总部之间内网通信需要租用专线(比如 MPLS,传输专线等);
但是专线价格昂贵,对于中小型企业,或者跨国公司来说,成本较高;
由于 Internet 的发展,Internet 网有了足够的带宽和覆盖,通过 Internet 建立分支-总部内网通信的可行性越来越高;
解决方案
GRE(Generic Routing Encapsulation,通用路由封装协议)就是在这种背景下被提出的;
GRE 是种 Layer 3 VPN 封装技术。GRE 能够对某些网络层协议(如 IPX、IPv4、IPv6 等)的报文进行封装,使封装后的报文能够在另一种网络中(如 IPv4)传输,从而解决跨越异种网络的报文传输问题;
原理简述
GRE 提供了将一种协议的报文封装在另一种协议报文中的机制,是一种三层隧道封装技术,使报文可以通过 GRE 隧道透明的传输;
GRE 技术本质上是一种隧道技术,可以对某些网络层协议(如 IPX、IPv6、IPv4 等)的数据报文进行封装,使这些被封装的数据报文能够在另一个网络层协议(如 IPv4、IPv6 等)中传输;

特性说明
GRE 实现机制简单,对隧道两端的设备负担小; GRE 隧道可以通过 IPv4 网络连通多种网络协议的本地网络,有效利用了原有的网络架构,降低成本; GRE 隧道将不连续的子网连接起来,用于组建 VPN,实现企业总部和分支间的连接; GRE 只有简单的密码验证,没有加密功能;
GRE 隧道能够承载 IPv4/IPv6 的:单播、组播、广播报文; 1)由于动态路由协议中会使用组播报文,因此更多时候 GRE 会在需要传递组播路由数据的场景中被用到,这也是 GRE 被称为通用路由封装协议的原因;
应用场景
IPv6 over IPv4
通过在 IPv4 网络上建立 GRE 隧道,解决两个 IPv6 网络的通信问题:
广域互联
通过 GRE 隧道,分支和总部之间可以基于 Internet 建立企业网络,解决了企业分支与总部互联的问题;

GRE 隧道能承载 IPv4/IPv6 单播、组播、广播报文,分支-总部之间可以通过 GRE 隧道建立内网之间的动态路由协议邻居,使得分支-总部之间内网互联更加方便;

通过 GRE 接入 MPLS VPN 网络
在 MPLS VPN 中,为了让 CE 设备接入 VPN 中往往需要 CE 与 MPLS 骨干网的 PE 设备之间有直接的物理链路;
在实际组网中,并非所有的 CE 和 PE 都能用物理链路直接相连。例如,很多已经连接到 Internet 或[……]

READ MORE

「GRE」- 概念、术语

隧道接口(Tunnel Interface)
隧道接口(Tunnel Interface)是为实现报文的封装而提供的一种点对点类型的虚拟接口,与 Loopback 接口类似,都是一种逻辑接口;
负责发送封装后的报文的物理接口叫做隧道源接口,对端接收此报文的物理接口叫做隧道目的接口;
基本原理
GRE 构成要素分为 3 个部分: 1)乘客协议,指用户在传输数据时所使用的原始网络协议; 2)封装协议,就是用来“包装”乘客协议对应的报文,使原始报文能够在新的网络中传输; 3)运输协议,是指被封装以后的报文在新网络中传输时所使用的网络协议;

如图所示,乘客协议为 IPv6,封装协议为 GRE,运输协议为 IPv4;
整体转发流程如下: 1)当 R1 收到 IP1 发来的 IPv6 数据包,查询设备路由表,发现出接口是隧道接口,则将此报文发给隧道接口处理; 2)隧道接口给原始报文添加 GRE 头部,然后根据配置信息,给报文加上 IP 头。该 IP 头的源地址就是隧道源地址,IP 头的目的地址就是隧道目的地址; 3)封装后的报文在 IPv4 网络中进行普通的 IPv4 路由转发,最终到达目的地 R2,并解封装(解封装过程和封装过程相反,这里不再赘述)
GRE Over IPSec
GRE 的主要缺点是不支持加密和认证,数据的安全传输得不到很好的保障; 而 IPSec 的主要缺点是只支持 IP 协议,且不支持组播;
将 GRE 封装入 IPsec 可以结合 GRE 和 IPsec 的优点,避免各自的缺点。GRE Over IPsec 是一种企业常用的点到点 VPN 技术;
通过部署 GRE Over IPSec 结合两种 VPN 技术的优点:
GRE 可以封装组播数据并在 GRE 隧道中传输。而 IPsec 目前只能对单播数据进行加密保护,因此对于诸如路由协议、语音、视频等组播数据需要在 IPsec 隧道中传输的情况,可以通过建立 GRE 隧道,并对组播数据进行 GRE 封装,然后再对封装后的报文进行 IPsec 的加密处理,就实现了组播数据在 IPsec 隧道中的加密传输;
GRE Over IPsec 可以结合 GRE 和 IPsec 两种技术的优点,使网络既可以支持支持多种上层协议和组播报文,又可以支持报文加密、身份认证机制和数据完整性校验;
当网关之间采用 GRE over IPsec 连接时,先进行 GRE 封装,再进行 IPsec 封装;
GRE over IPsec 可以使用两种封装模式:隧道模式;传输模式;
DSVPN
DSVPN 主要解决 GRE Over IPsec 存在的一些缺陷,使得有大量分支机构的公司也能方便地搭建 VPN[……]

READ MORE

「GRE」- 基本工作原理

数据转发
GRE 隧道是三层隧道,主要承载 IPv4/IPv6 报文。GRE 通过封装外层 IP 头部,使得数据可在公网上传递

存活检测
由于 GRE 协议并不具备检测链路状态的功能,如果对端接口不可达,隧道并不能及时关闭该 Tunnel 连接,这样会造成源端会不断的向对端转发数据,而对端却因隧道不通接收不到报文,由此就会形成流量中断;
GRE 的 Keepalive 检测功能可以检测隧道状态,即检测隧道对端是否可达;
Keepalive 超时时间=发送周期(默认 5 s)*重试次数(默认 3 次)

Keepalive 检测功能的实现过程如下:
1)当 GRE 隧道的源端使能 Keepalive 检测功能后,就创建一个定时器,周期地发送 Keepalive 探测报文,同时通过计数器进行不可达计数。每发送一个探测报文,不可达计数加 1;
2)对端每收到一个探测报文,就给源端发送一个回应报文。如果源端的计数器值未达到预先设置的值就收到回应报文,就表明对端可达;
3)如果源端的计数器值到达预先设置的值——重试次数(Retry Times)时,还没收到回送报文,就认为对端不可达。此时,源端将关闭隧道连接。但是源端口仍会继续发送 Keepalive 报文,若对端 Up,则源端口也会 Up,建立隧道链接;[……]

READ MORE