Linux系统-部署-运维系列导航

 


 

查看excel的最大行
打开一个excel,
按ctrl + ↓,可得最大行数,
按ctrl + →可得最大列数。
 

 

1.shell和函数库封装系统调用,系统调用时内核功能的接口
2.用户态与内核态
用户态转换内核态:系统调用(主动,软中断),异常事件如缺页异常(被动),外围设备中断(被动,硬中断)
 

关机:
1. poweroff 
2. init 0  
3. shutdown -h now

 

重启:
1. reboot  
2. init 6  
3. shutdown -r now

 

登录界面:
init 3: 登录到纯字符界面
init 5: 登录到图形界面 (前提是安装了server   with    GUI)
startx: 从字符界面退到图形界面(前提是安装了server   with    GUI )

 


切换用户,su root 与 su - root
有 - 选项,切换用户身份更彻底;反之,只切换了一部分,这会导致某些命令运行出现问题或错误
-:也可以 -l(小写L),当前用户不仅切换为指定用户的身份,同时所用的工作环境也切换为此用户的环境(包括 PATH 变量、MAIL 变量等)
使用 - 选项可省略用户名,默认会切换为 root 用户。

注意,使用 su 命令时,有 - 和没有 - 是完全不同的,- 选项表示在切换用户身份的同时,连当前使用的环境变量也切换成指定用户的。
环境变量是用来定义操作系统环境的,因此如果系统环境没有随用户身份切换,很多命令无法正确执行。

举个例子
普通用户 lamp 通过 su 命令切换成 root 用户,但没有使用 - 选项,
这样情况下,虽然看似是 root 用户,但系统中的 $PATH 环境变量依然是 lamp 的(而不是 root 的),
因此当前工作环境中,并不包含 /sbin、/usr/sbin等超级用户命令的保存路径,这就导致很多管理员命令根本无法使用。
不仅如此,当 root 用户接受邮件时,会发现收到的是 lamp 用户的邮件,因为环境变量 $MAIL 也没有切换。

 


执行命令 command option args
其中,options一般规则
单字母/短格式 选项前一般都带有一个横线 -,例如-a,-b,c,多个短格式选项可以写在一起,如 -abc
全字/长格式 选项前通常带有两个横线 --,例如:--help,--version

 

获取命令帮助
command --help
man command
info   command

 

命令行编辑的几个辅助操作
#快捷键不区分大小写
Tab键:自动补齐
反斜杠“\”:强制换行
快捷键 Ctrl+U:清空至行首
快捷键 Ctrl+K:清空至行尾
快捷键 Ctrl+A:跳转至行首
快捷键 Ctrl+E:跳转至行尾
快捷键 Ctrl+L:清屏
快捷键 Ctrl+C:取消本次命令编辑

 

chmod命令,设置文件/目录的权限
格式1:chmod   [ugoa]  [+-=]  [rwx]  文件或目录... 
格式2:chmod nnn 文件或目录(多个逗号分割),其中nnn为3位八进制数

常用命令选项
-R:递归修改指定目录下所有文件、子目录的权限

 

chown命令,设置文件/目录的归属
格式1:chown  拥有人   文件或目录
              
格式2:chown  :拥有组  文件或目录
              
格式3:chown  拥有人:拥有组  

常用命令选项
-R:递归修改指定目录下所有文件、子目录的归属

 

特殊符号
\ 反斜杠,去除特殊符号的意义、用在一行的末尾,那么他就是分行符        
例如:需要输出 "echo    you    cost:   $5.00"         
echo    you    cost:   \$5.00

"" 双引号,遇到任何特殊字符均转义,均当特殊字符来用,即双引号中特殊字符需要\转义

'' 单引号,遇到任何特殊符号均不转义,不当特殊字符来用,就是一个普通字符
         
 $       `        \         !        *       ? 

 


关于Linux服务器并发TCP连接数量,参考如下教程
 
需要同时调整如下信息
1.可用端口范围 sysctl  net.ipv4.ip_local_port_range
2.系统级打开文件数 sysctl fs.file-max
3.系统级单个进程打开文件数  sysctl  nr_open
4.用户进程级打开文件数 ulimit 
 
配置用户级限制:nproc=用户可以运行的进程数量,nofile=用户每个进程可以打开的文件数量,包括socket(tcp/udp)、打开文件
#当前登录生效
ulimit -n 65536
 
#永久生效
/etc/security/limits.conf
*    -    nproc        65535
*    -    nofile        65535

#合并脚本 echo -e 使字符串支持转义字符\n  \t等
ulimit -n 65535 && echo -e "*\t-\tnproc\t65535\n*\t-\tnofile\t65535" >> /etc/security/limits.conf

 


linux 标准输入保存文件

1.覆盖文件

tee test.txt <<-EOF

cat > test.txt <<-EOF
tee > test.txt <<-EOF

echo -e "hello\nworld" > test.txt

 

2.追加文件

tee -a test.txt <<-EOF

cat >> test.txt <<-EOF
tee >> test.txt <<-EOF

echo -e "hello\nworld" >> test.txt

 

特别关注

  1. cat必须有重定向符号,否则要么报文件不存在,要么只是打印现有内容,无法保存输入内容
  2. tee语法:tee 选项 文件,其中选项常用 -a=追加,-i=忽略终端符号ctrl + c
  3. <<-EOF,表示输入结束符,可以是任何字符串,其中 - 符号表示,结束符前后可以有空白符,如空格或制表符,所以指定 <<EOF 时结束符必须是新行顶格写EOF,不能有空白符
  4. 如果不指定结束符,则默认为 ctrl + d
  5. echo指定 -e 支持转义字符,否则转义字符将直接输出

 


nohup 与 &
  • nohup,非中断运行模式,可以免疫终端关闭(session关闭)或用户退出,但不免疫Ctrl C;
  • &,后台运行模式,可以免疫Ctrl C,但无法免疫终端关闭或用户退出
  • nohup command &,持续后台运行模式

 


shell脚本,定位到当前目录
cd $(dirname $0);
 

ps -ef
[root@localhost ~]# ps -ef | head
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 15:18 ?        00:00:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root         2     0  0 15:18 ?        00:00:00 [kthreadd]
root         4     2  0 15:18 ?        00:00:00 [kworker/0:0H]
root         6     2  0 15:18 ?        00:00:00 [ksoftirqd/0]
root         7     2  0 15:18 ?        00:00:00 [migration/0]
root         8     2  0 15:18 ?        00:00:00 [rcu_bh]
root         9     2  0 15:18 ?        00:00:00 [rcu_sched]
root        10     2  0 15:18 ?        00:00:00 [lru-add-drain]
root        11     2  0 15:18 ?        00:00:00 [watchdog/0]

 

ps -aux
[root@localhost ~]# ps -aux | head
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.3 128304  6880 ?        Ss   15:18   0:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root         2  0.0  0.0      0     0 ?        S    15:18   0:00 [kthreadd]
root         4  0.0  0.0      0     0 ?        S<   15:18   0:00 [kworker/0:0H]
root         6  0.0  0.0      0     0 ?        S    15:18   0:00 [ksoftirqd/0]
root         7  0.0  0.0      0     0 ?        S    15:18   0:00 [migration/0]
root         8  0.0  0.0      0     0 ?        S    15:18   0:00 [rcu_bh]
root         9  0.0  0.0      0     0 ?        S    15:18   0:00 [rcu_sched]
root        10  0.0  0.0      0     0 ?        S<   15:18   0:00 [lru-add-drain]
root        11  0.0  0.0      0     0 ?        S    15:18   0:00 [watchdog/0]

 

特别关注
可以通过 ps -aux | grep sort -rnk num 实现根据进程资源消耗来排序,其中sort命令参数
-r = 降序/逆序/反序
-n = 按照数字格式排序,其中字母按照ASCII码
-k = 指定排序列,从1开始,如 ps -aux | grep sort -rnk 3表示按照cpu使用率降序,ps -aux | grep sort -rnk 4表示按照内存使用率降序
 

Linux telnet
安装:yum install -y telnet
使用:telnet ip port
其中,退出方式为 ctrl + ],进入命令模式,然后输入quit。
进入命令模式的方式可以通过参数指定,telnet ip port -e char,指定单个字符,如telnet ip port -e c,则输入c即可进入命令模式

Linux下可以使用 curl  代替 telnet

tcp: 
curl -v telnet://ip:port

http:
curl -v http://ip:port
 

 


vim
显示隐藏行号
:set nu
:set nonu

 

查找模式不区分大小写
方法一:
查找时使用\c参数
进入底行模式,输入命令“/string\c ” 或 “/\cstring”,将会忽略大小写查找string字符串。
注意:\c与字符串之间不要有空格,因为该空格也会被认为是查询的字符串

 

方法二:
通过设置vim配置来忽略大小写查找。
:set ignorecase 或 set ic 忽略大小写查找
:set noignorecase 或set noic 严格大小写查找
临时的话,在底行模式,输入命令 set ignorecase 或 set ic,在没关闭该文件前提下,字符串的查找都将不区分大小写

 


正则表达式匹配双字节字符,如汉字
[^\x00-\xff]

 


清空文件
1.使用vi/vim命令打开文件后,输入"%d"清空,后保存即可。但当文件内容较大时,处理较慢,命令如下:vim filename:%d:wq
2.cat /dev/null > filename
3.echo "" > filename,echo > filename,此时会在文件中写入一个空行“\n"
4.cp /dev/null filename
5.> filename

 


windows编辑脚本,上传到Linux,执行异常,需要格式转换
查看脚本文件是dos格式还是unix格式的几种办法
1cat -A filename 从显示结果可以判断,dos格式的文件行尾为^M$,unix格式的文件行尾为$;
(2)vim filename打开文件,执行 :set ff,如果文件为windows格式在显示为fileformat=dos,如果是unxi则显示为fileformat=unix。

 

修改文件格式
1.使用 dos2unix,直接把文件转换为unix格式
yum install -y dos2unix
dos2unix filename

 

2.使用sed命令
sed -i "s/\r//" filename 或者 sed -i "s/^M//" filename

 

3.vim更改
vi filename,
执行 :set ff=unix 设置文件为unix
执行 :wq,保存

 


shell脚本退出状态
  • shell返回码,标识整个脚本的执行结果状态,用“exit 返回码”表示,1-255。
  • 函数返回码,标识一个函数的执行结果状态,用“return 返回码”表示。
  • 命令返回码,标识一个命令的执行结果状态,在命令执行后,紧跟着获取返回码,用"$?"获取
退出码的值
含义
例子
注释
0
成功
 
0为成功,非0(大于0)失败
1
通用错误
let var1 = 1/0
各种各样的错误都可能使用这个退出码, 比如除0错误
2
shell内建命令使用错误
 
很少看到, 通常情况下退出码都为1
126
命令调用不能执行
 
程序或命令的权限是不可执行的
127
command not found
 
估计是$PATH不对, 或者是拼写错误
128
exit的参数错误
exit 3.14159
exit只能以整数作为参数, 范围是0 - 255(见脚注)
128+n
信号n的致命错误
kill -9 脚本的$PPID
$? 返回137(128 + 9)
130
用Control-C来结束脚本
 
Control-C是信号2的致命错误, (130 = 128 + 2, 见上边)
255*
超出范围的退出状态
exit -1
exit命令只能够接受范围是0 - 255的整数作为参数

 


在windows的DOS操作界面里面,清屏的命令
cls

 

linux清屏操作如下
  1. clear命令、这个命令将会刷新屏幕,本质上只是让终端显示页向后翻了一页,如果向上滚动屏幕还可以看到之前的操作信息。
  2. Ctrl+l(小写的L)、这是一个清屏的快捷键,清屏效果同clear命令一样。
  3. reset命令、这个命令将完全刷新终端屏幕,之前的终端输入操作信息将都会被清空,这样虽然比较清爽,但整个命令过程速度有点慢,使用较少。
值得一提的是reset命令在你的终端控制错乱时非常有用。如输入字符不出现在光标的位置的情况。还有当你敲击回车键时,新提示符并没有出现在新行上而是出现在老提示符的前面。此时reset命令就能用来修正这些问题。
 

#查看系统版本
#内核版本
[root@localhost ~]# uname -r
3.10.0-1160.el7.x86_64

#系统版本
[root@localhost ~]# cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (Core)

#CPU架构
[root@localhost ~]# arch
x86_64

#完整信息(系统版本,内核版本,CPU架构)
[root@localhost ~]# uname -a
Linux localhost.localdomain 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

 

# 查看物理CPU个数
cat /proc/cpuinfo | grep 'processor' | wc -l

 

# 查看每个物理CPU中core的个数(即核数)
cat /proc/cpuinfo| grep "cpu cores"| uniq

 

# 查看cpu信息,包括核心数
lscpu

 

#查看内存信息
1.cat /proc/meminfo | grep -i total
2.free -(k/m/g)

 

#磁盘工具命令

fdisk磁盘分区工具,可以查看,可以分区,与lsblk搭配
fdisk查看磁盘,找到新增/未分区磁盘,lsblk查看分区情况
fdisk [选项] <磁盘>    更改分区表
fdisk [选项] -l <磁盘> 列出分区表
选项
 -h                    打印此帮助文本
 -u[=<单位>]           显示单位:“cylinders”(柱面)或“sectors”(扇区,默认)

 

lsblk:List block device,树状结构列出所有磁盘、分区(ID)、挂载点,直观展示,优于blkid(行展示分区ID)
-f:同时列出文件系统名称
-p:列出该设备的完整文件名,而不是仅列出最后的名字

 

df:disk free,查看磁盘使用情况(文件系统的使用情况) 通过文件系统来快速获取空间大小的信息,包括被删除但在文件系统中未消失的文件
-h 以人类可读的方式显示(k,m,g)
-T 显示分区的文件系统类型

 

du:disk usage,查看目录或文件大小,通过搜索文件来计算每个文件的大小后累加,只包含看得见的文件,不包括被删除的
du -sh [目录或文件 ./*]
-h:以人类可读的方式显示(k,m,g)
-s:只显示总和,不要显示其下子目录和文件占用的磁盘空间大小

 


telnet
telnet ip port
退出:ctrl+]    quit

 


java jvm参数
最大内存,初始内存,新生代内存(官方建议最大内存3/8),单线程内存
2g: -Xmx2048m -Xms1024m -Xmn1024m -Xss2048k
1g:  -Xmx1024m -Xms1024m -Xmn512m -Xss1024k

 


mysql日期
select NOW() #2022-10-12 13:55:32
,ADDDATE(NOW(),1) #2022-10-13 13:55:32
,CURRENT_DATE #2022-10-12
,ADDDATE(CURRENT_DATE,interval 1 DAY)  #2022-10-13
,DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i:%s') #2022-10-12 13:55:32
,DATE_FORMAT(NOW(),'%Y-%m-%d 00:00:00') #2022-10-12 00:00:00
,DATE_FORMAT(ADDDATE(NOW(),1),'%Y-%m-%d 00:00:00') #2022-10-13 00:00:00
from dual;

 

clickhouse查询当天数据
between formatDateTime(today(),'%Y-%m-%d 00:00:00') and formatDateTime(addDays(today(),1),'%Y-%m-%d 00:00:00')

 


killall
杀死所有进程,指定进程名称
#信号名称大小写区分#
语法:killall [选项]  进程名称

选项:
-e | --exact : 进程需要和名字完全相符
-I | --ignore-case :忽略大小写
-r | --regexp :将进程名模式解释为扩展的正则表达式

-l | --list :列出所有的信号名称,HUP INT QUIT ILL TRAP ABRT IOT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM
STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS
UNUSED
-s | --signal :发送指定信号,值为 -l的输出结果,如-s KILL = -s 9 = -KILL = -9 强制杀掉进程 
常用的是HUP(1,终端断线),INT(2,中断,同<Ctrl>+c),QUIT(3,退出,同<Ctrl>+\),KILL(9,强制终止),
TERM(15,缺省信号,终止,正常结束),CONT(18,继续,同fg/bg命令),STOP(19,停止),TSTP(20,暂停,同<Ctrl>+Z)

 

kill
杀死进程,指定进程ID,一般搭配 ps 命令使用
#信号名称大小写不区分#
#查看信号
语法1:kill [-l <信号编号>] 
-l <信号编号>  若不加<信号编号>选项,则 -l 参数会列出全部的信号名称

[root@localhost ~]# kill -l
 1) SIGHUP     2) SIGINT     3) SIGQUIT     4) SIGILL     5) SIGTRAP
 6) SIGABRT     7) SIGBUS     8) SIGFPE     9) SIGKILL    10) SIGUSR1
11) SIGSEGV    12) SIGUSR2    13) SIGPIPE    14) SIGALRM    15) SIGTERM
16) SIGSTKFLT    17) SIGCHLD    18) SIGCONT    19) SIGSTOP    20) SIGTSTP
21) SIGTTIN    22) SIGTTOU    23) SIGURG    24) SIGXCPU    25) SIGXFSZ
26) SIGVTALRM    27) SIGPROF    28) SIGWINCH    29) SIGIO    30) SIGPWR
31) SIGSYS    34) SIGRTMIN    35) SIGRTMIN+1    36) SIGRTMIN+2    37) SIGRTMIN+3
38) SIGRTMIN+4    39) SIGRTMIN+5    40) SIGRTMIN+6    41) SIGRTMIN+7    42) SIGRTMIN+8
43) SIGRTMIN+9    44) SIGRTMIN+10    45) SIGRTMIN+11    46) SIGRTMIN+12    47) SIGRTMIN+13
48) SIGRTMIN+14    49) SIGRTMIN+15    50) SIGRTMAX-14    51) SIGRTMAX-13    52) SIGRTMAX-12
53) SIGRTMAX-11    54) SIGRTMAX-10    55) SIGRTMAX-9    56) SIGRTMAX-8    57) SIGRTMAX-7
58) SIGRTMAX-6    59) SIGRTMAX-5    60) SIGRTMAX-4    61) SIGRTMAX-3    62) SIGRTMAX-2
63) SIGRTMAX-1    64) SIGRTMAX

[root@clickhouse1 ~]# kill -l SIGKILL
9


#杀掉进程
语法2:kill [-s <信号名称或编号>]  进程ID
-s <信号名称或编号>  指定要送出的信号,值为 -l 的输出结果,如-s 9 = -s SIGKILL = -SIGKILL = -9 强制杀掉进程

 

pkill
与killall类似,杀死所有进程,指定进程名称格式为 正则表达式
#信号名称大小写不区分#
语法:pkill [选项]  进程名称正则表达式

选项:
-o:仅向找到的最小(oldest起始)进程号发送信号
-n:仅向找到的最大(newest结束)进程号发送信号
-x:匹配完成进程名
-<sig 信号名称或编号>  指定要送出的信号,信号与kill命令相同,但信号名称或编号直接在符号 - 之后,如 -SIGKILL = -9,不支持 -sig 9

 

特别关注:mysqld
mysqld进程默认存在守护进程,识别进程信号,如果通过以上kill、killall、pkill等命令,如果发送了信号(如-9、-KILL等),则mysqld进程默认重新启动,以新的进程ID运行;
如果不发送信号,直接 kill pid、killall pname、pkill pname,则可以正常杀掉进程;
特别建议:使用组件原生方式停止服务(service mysqld stop),避免进程强制停止而产生数据不完整等故障
 

获取进程ID,ps命令,pgrep命令,pidof命令
pgrep
默认只显示进程ID,多个进程ID换行分隔
语法:pgrep 选项 进程名称
选项:
-o:仅显示找到的最小(起始)进程号;
-n:仅显示找到的最大(结束)进程号;
-l:同时显示进程ID与进程名称;

进程名称支持部分匹配,如pgrep java 与 pgrep jav

 

pidof
多个进程ID,空格分隔
语法:pidof 选项 进程名称
选项:
-s:一次只显示一个进程号
-c:只显示运行在root目录下的进程,这个选项只对root用户有效
-o:忽略指定进程号的进程

进程名称必须完整匹配,如pgrep java 不可以写成 pgrep jav

 


ls排列文件
按大小排序
ls -hlS  #从大到小
ls -hlSr #从小到大

按创建时间排序
ls -hlt  #从新到旧
ls -hltr #从旧到新

 


top命令

 

交互命令

 

特别关注:top命令在脚本中执行的问题
top命令在脚本中执行时,会报“TERM environment variable not set“,由于脚本中无法加载默认终端类型
方案:使用 -b 参数,即批次存档模式,搭配 -n(指定行数) 一起表示将结果输出到当前脚本内
top -bn 1 -p xxxx
示例:result=`top -bn 1 -p mysqld`

 


less命令,不会全部加载,可以前后滚动,可以前后搜索

 


head/tail
head/tail 前/后 10行
head/tail -n 10 前/后 10行
head/tail -n -10 从倒数第10行开始,取到头/head/tail -n +10 从第10行开始,取到头/尾

 


Nginx命令
nginx 启动nginx
nginx -s reload|reopen|stop|quit  #重新加载配置|重启|停止|退出 nginx
nginx -t   测试配置是否有语法错误

nginx [-?hvVtq] [-s signal] [-c filename] [-p prefix] [-g directives]

-?,-h           : 打开帮助信息
-v              : 显示版本信息并退出
-V              : 显示版本和配置选项信息,然后退出
-t              : 检测配置文件是否有语法错误,然后退出
-q              : 在检测配置文件期间屏蔽非错误信息
-s signal       : 给一个 nginx 主进程发送信号:stop(停止), quit(退出), reopen(重启), reload(重新加载配置文件)
-p prefix       : 设置前缀路径(默认是:/usr/local/Cellar/nginx/1.2.6/-c filename     : 设置配置文件(默认是:/usr/local/etc/nginx/nginx.conf)
-g directives   : 设置配置文件外的全局指令

 


find级联执行命令
find [查找起始路径] [查找条件] [处理动作]
-maxdepth 1 递归目录层次
 
1.起始路径可以直接通配多个文件,路径中包含通配符,无需使用引号或转义,区别以下 -name
find /usr/local/study/*.txt | xargs ls -l

 

2.查找条件 -name,参数应该明确到完整文件名
  • 可以包含通配符,但通配符需要单引号或双引号包裹,或转义字符\*表示,否则会报错:路径必须在表达式之前(paths must precede expression)
  • 可以包含空格,但空格需要单引号或双引号包裹,或转义字符 \空格 表示,因为命令无法识别空格属于文件名还是用来区分多个参数
如 abc.txt,则 -name abc.txt 或 "abc*" 或 abc\*

如果没有引号,Linux是直接将 * 替换为当前目录下的所有文件,所以会报错。 即如果find命令需要接受的是通配符*,需要通过引号或者转义才能真正表达*。 [root@localhost dir2]# ls txt11.txt txt12txt.txt txt1.txt [root@localhost dir2]# echo * txt11.txt txt12txt.txt txt1.txt [root@localhost dir2]# find . -name *.txt find: 路径必须在表达式之前: txt12txt.txt 用法: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression] [root@localhost dir2]# find . -name "*.txt" ./txt1.txt ./txt11.txt ./txt12txt.txt [root@localhost dir2]# find . -name \*.txt ./txt1.txt ./txt11.txt ./txt12txt.txt

 

3.查找条件 -path,参数应该明确完整路径(包括文件名),可以包含通配符,但与 -name 相同,需要通过引号或转义表示
   如 /data/log/abc.txt,则 -path "*abc*",或者 "*abc.txt"

 

4.处理动作(命令前的横线符号不能缺失),可以 -print,-ls,-delete,-exec COMMAND {} \;(一对花括号+空格+反斜杠+分号,因为分号代表命令结束,而分号又是特殊字符,所以需要反斜杠转义)或者通过管道 xargs
find . -mtime +7 -exec rm -rf {} \;
find . -mtime +7 | xargs rm -rf

 

5. find 计数
windows
find /c "string"

linux
wc -l
grep -c "string"

 


关于find exec 与 find xargs
  1. exec格式为 "-exec COMMAND {} \;",xargs格式为 "xargs COMMAND"(关于xargs -i/I参数参考下文)
  2. exec实际上每一条结果执行一次,效率较低,xargs默认批次执行,效率高(默认批次为5000,可以通过 -n num指定)
  3. xargs默认批次可能引起参数过长错误(如果文件名超长,文件个数超多)
  4. xargs不支持文件名包含空格,因为xargs无法区分是文件名的空格,还是多个文件的分隔符,exec没有空格问题

关于xargs 与 管道 |
  1. 管道是将前面命令的输出作为后面命令的标准输入,传递的是结果本身,文件名,文件内容等
  2. xargs是将前面命令的输出,作为后面命令的参数,传递的是结果代表的对象,如文件
 

关于xargs -i/-I区别(大小写)
-i 默认选项,直接使用 {} 作为替换符号(占位符)代表前面命令的输出,但不能明确指定{}
find / -name '*test*.txt' | xagrs -i mv {} /test,而不能 xagrs -i {} mv {} /test

 

-I 可以指定替换符号
find / -name '*test*.txt' | xagrs -I {} mv {} /test  -->  find / -name '*test*.txt' | xagrs -I abcd mv abcd /test

 

特别关注
  • xargs后如果没有明确指定,默认为 -i,且 {} 在最后(-i 与 {} 都可以省略),find dir1 -name "*.txt" | xargs grep "sth" 相等于 find dir1 -name "*.txt" | xargs -i grep "sth" {}
  • 如果参数不是在命令最后,则需要明确使用 -i/I 来指定(不可以省略),如 find dir1 -name "*.txt" | xargs -i mv {} dir2/ 或 find dir1 -name "*.txt" | xargs -I {} mv {} dir2/

 


find根据时间范围查找文件
Linux中的文件有访问时间(atime)、数据修改时间(mtime)、状态修改时间(ctime)这三个时间,我们也可以按照时间来搜索文件。(注意:如果以time结尾的时间单位,默认单位时间是天。)
命令格式:
find 搜索路径 [选项] 搜索内容
选项:
-atime[+|-]时间:按照文件访问时间搜索
-mtime[+|-]时间:按照文件数据(如内容)修改时间搜索
-ctime[+|-]时间:按照文件状态(如权限)修改时间搜索

 

特别关注:也有-amin、-mmin等时间选项,时间单位为分钟。
用mtime数据修改时间来举例,重点说说+和-时间的含义。
我们画一个时间轴,来解释一下

 

说明:
-5:代表5天内修改的文件。
5:代表前5~6天,那一天修改的文件。
+5:代表6天前修改的文件

 


//以下各命令中【文件 或 目录】支持多个,空格分隔
tar打包,将多个文件打包成一个,支持压缩,如 -z(gzip)
1.压缩 tar -zcvf *.gz files-to-be-compressed (-c create -f 文件名)
2.解压 tar -zxvf *.gz -C other-dir 解压到指定目录 (-x extract -v verbose 显示详细信息)
-c: --create: 建立压缩档案
-x:--extract, --get : 解压
-t:--list : 列出tar归档文件中包含的文件或目录
-r:--append : 向压缩归档文件末尾追加文件
-u:--update : 更新原压缩包中的文件

这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个。下面的参数是根据需要在压缩或解压档案时可选的。

-C: --directory=DIR : 执行归档动作前变更工作目录到 目标DIR
-z:--gzip : 有gzip属性的
-v:--verbose : 显示所有过程

如果要指定文件名,参数 -f 是必须的
-f: --file=ARCHIVE : 使用档案名字,切记,这个参数是最后一个参数,后面只能接档案名。

 

zip压缩,可以针对文件 和 文件夹
zip [参数] [压缩后的文件名] [将要压缩的文件或目录]
  1. zip -r temp.zip temp/ 递归压缩
  2. zip -q -r temp.zip temp/ 安静递归,不显示信息
  3. zip temp.zip temp.log 文件压缩
unzip解压缩
unzip [参数][-P <密码>][.zip文件][文件][-d <目 录>][-x <文件>]
  1. -l   显示压缩文件内所包含的文件。
  2. -n   解压缩时不要覆盖原有的文件。
  3. -o   不必先询问用户,unzip执行后覆盖原有文件。
  4. -P<密码>   使用zip的密码选项。
  5. -q   执行时不显示任何信息。
  6. [.zip文件]   指定.zip压缩文件。
  7. [文件]   指定 要处理.zip压缩文件中的哪些文件,空格分隔
  8. -d<目录>   指定文件解压缩后所要存储的目录。
  9. -x<文件>   指定不要处理.zip压 缩文件中的哪些文件,空格分隔
 
zipinfo查看zip文件内容
  1. -1只列出文件名
  2. -l列出详细信息
 
gzip压缩,只针对文件,每个文件压缩成一个.gz,区别于打包;默认压缩/解压后,源文件删除,可以使用 -c 参数重定向
gzip[参数][文件或者目录]
  1. 压缩 gzip -rv dir gzip -v file1 file2
  2. 解压 gzip -rdv dir
-d或--decompress或----uncompress  解开压缩文件。 
-c或--stdout或--to-stdout  把内容输出到标准设备,不改变原始文件。  gzip -cv file > file.gz;
-c 还可用于检索压缩日志文件, gzip -dc *.log.gz | grep -a sth
-f或--force  强行压缩文件。不理会文件名称或硬连接是否存在以及该文件是否为符号连接。
-q或--quiet  不显示警告信息。 
-r或--recursive  递归处理,将指定目录下的所有文件及子目录一并处理。
-v或--verbose  显示指令执行过程。
-l或--list        查看压缩文件信息,包括压缩前后大小,压缩率
-num 用指定的数字num调整压缩的速度,-1或--fast表示最快压缩方法(低压缩比),-9或--best表示最慢压缩方法(高压缩比)。系统缺省值为6。

 


grep -a: 处理二进制文件,就像它是文本;这相当于--binary-files = text选项。不忽略二进制的数据。
grep -c:统计匹配的行数,如果有多个文件,则按照文件分别展示结果;
grep -C num: 显示匹配行以及前后num行
grep | wc -l:统计匹配的次数,如果有多个文件,则展示总和
grep -v:反向匹配,显示不能被表达式匹配的行
grep -o:将匹配到的非空字符串打印,每行打印一个,所以可以用于统计一行或整个文本中的字符串数量,grep -o sth | wc -l
grep -n:打印匹配的行号
grep -H/h:是否打印文件名(显示文件名,-H打印,-h不打印),不同场景时不同默认值,建议明确指定
grep -r/grep -d recurse:递归遍历子目录(grep默认只遍历当前目录)
grep -d skip:只遍历当前目录,即跳过子目录,此为grep默认操作
grep -d 动作:指定子目录的动作,如skip,recurse
 

gzip, grep,ls等通配符匹配文件时,如果文件名包含空格,使用引号 “a b.c” 或者转义字符 a\ b.c,其中,使用引号时不可使用通配符如*
 

linux操作json
jq -c '{time:.time,ip:.ip,ora_get_line:.ora_get_line}' pisces_leadsafe.txt | grep 10.66.110.131 | grep 2018111714

 


查看网络连接 netstat
windows:
netstat -ano | findstr 8080 | findstr -i listening o标识进程id
tasklist | findstr -i notepad 根据名称查找进程,不区分大小写
tasklist /fi "pid eq 35342" 根据进程id查找进程 fi=filter
taskkill /pid 35342 根据pid强制结束进程; /f 强制
taskkill /im notepad.exe 根据进程名称结束进程 /f 强制,可以使用通配符 note*
 
tasklist/taskkill /fi 筛选器如下

 

linux:
netstat -antup | grep 8080 | grep -i listen #p标识进程id和进程名
netstat -lntup | grep 8080 l=listening #a=all
 
特别关注
使用netstat 统计不同状态TCP连接数量
//NR>2由于netstat命令前2行输出为描述信息
[root@localhost ~]# netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:33071           0.0.0.0:*               LISTEN      2105/mysqld         
tcp        0      0 0.0.0.0:7379            0.0.0.0:*               LISTEN      1090/redis-server 0 
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1244/sshd           

[root@localhost ~]# netstat -antp | awk -F '[ /]+' 'NR>2 {count[$6]++} END {for(state in count) print state,"\t\t",count[state] }'
LISTEN          16
CLOSE_WAIT          2
ESTABLISHED          273
FIN_WAIT2          1
TIME_WAIT          1

 

使用netstat统计指定状态TCP连接不同进程数量
[root@localhost ~]# netstat -antp | grep -i established | awk -F '[ /]+' '{count[$8]++} END {for(app in count) print app,"\t\t",count[app] }'
java          124

mysqld          109
clickhouse-ser          6
sshd:          1
redis-server          31

 


split分割大文件
split [--help][--version][-<行数>][-b <字节>][-C <字节>][-l <行数>][要切割的文件][输出文件名前缀]
  • -<行数> 或 -l : 指定每多少行切成一个小文件
  • -a, --suffix-length=N 后缀长度,默认为2(字母则 aa ab ac, 数字则 00 01 02)
  • -b<字节> : 指定每多少字节切成一个小文件
  • --help : 在线帮助
  • --version : 显示版本信息
  • -C<字节> : 与参数"-b"相似,但是在切 割时将尽量维持每行的完整性
  • [输出文件名前缀] : 设置切割后文件的前置文件名, split会自动在前置文件名后再加上编号
  • -d 后缀名为数字,默认为字母(aa,ab,ac),默认从0开始
  • --numeric-suffixes[=FROM] 后缀为数字,可以指定from基础数字

 


scp
复制文件
指定了用户名,命令执行后需要输入用户密码
scp local_file remote_username@remote_ip:remote_folder 
scp local_file remote_username@remote_ip:remote_file 
第1个仅指定了远程的目录,文件名字不变,第2个指定了文件名

不指定用户名,命令执行后需要输入用户名和密码
scp local_file remote_ip:remote_folder  
scp local_file remote_ip:remote_file
第3个仅指定了远程的目录,文件名字不变,第4个指定了文件名  

 

复制目录
scp -r local_folder remote_username@remote_ip:remote_folder 
scp -r local_folder remote_ip:remote_folder  
第1个指定了用户名,命令执行后需要输入用户密码;  
第2个没有指定用户名,命令执行后需要输入用户名和密码

 


 

iftop linux流量监控工具
安装:
yum install -y epel-releaseyum install -y iftop

 

ps:如果安装源失败,尝试手工安装
CentOS/RHEL 5 :
rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-5.noarch.rpm

CentOS/RHEL 6 :
rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm

CentOS/RHEL 7 :
rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

 

运行
语法 iftop [option]
-i设定监测的网卡,如:# iftop -i eth1
-B 以bytes为单位显示流量(默认是bits),如:# iftop -B
-n 使host信息默认直接都显示IP,如:# iftop -n
-F net/mask显示特定网段的进出流量,如# iftop -F 10.10.1.0/24或# iftop -F 10.10.1.0/255.255.255.0

 

运行结果
界面上面显示的是类似刻度尺的刻度范围,为显示流量图形的长条作标尺用的。
中间的<= =>这两个左右箭头,表示的是流量的方向。
TX:发送流量
RX:接收流量
TOTAL:总流量
Cum:运行iftop到目前时间的总流量
peak:流量峰值
rates:分别表示过去 2s 10s 40s 的平均流量

 

运行界面交互指令
按h切换是否显示帮助;

--IP显示
按n切换显示本机的IP或主机名;

------端口显示--------
***按p切换是否显示端口信息;
***按N切换显示端口号或端口服务名称;

--流量控制
***按T切换是否显示每个连接的总流量;
按t切换显示格式为2行/1行/只显示发送流量/只显示接收流量;
按b切换是否显示平均流量图形条;

------过滤------
***按l打开屏幕过滤功能,输入要过滤的字符,比如ip,按回车后,屏幕就只显示这个IP相关的流量信息;

------排序------
按1或2或3可以根据右侧显示的三列流量数据进行排序;
按<根据左边的本机名或IP排序;
按>根据远端目标主机的主机名或IP排序;

--翻页
按j或按k可以向上或向下滚动屏幕显示的连接记录;

--刷新控制
***按P切换暂停/继续显示;
***按q退出监控。

 


输入输出重定向
1代表标准输出strout
2代表标准异常输出strerr
 
> 覆盖方式,将标准输出重定向到文件
>> 追加方式,将标准输出重定向到文件
 
1>1.txt 2>&1 等效于 &>1.txt 标准输出与标准异常输出全部重定向到1.txt
 

 Linux系统颜色默认表示的文件类型

蓝色表示目录;
绿色表示可执行文件;
红色表示压缩文件;
浅蓝色表示链接文件;
灰色表示其它文件;
红色闪烁表示链接的文件有问题了(如丢失);
黄色是设备文件,包括block, char, fifo。

 


CentOS配置JDK

export JAVA_HOME=/usr/local/jdk1.8.0_181
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib:$CLASSPATH
export JAVA_PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin
export PATH=$PATH:${JAVA_PATH}

 

mysql安装初始化
#mysql 临时密码
grep 'temporary password' /var/log/mysqld.log #具体日志路径以/etc/my.cnf为准

#第一次登陆修改密码
mysql -uroot -p
ALTER USER 'root'@'localhost' IDENTIFIED BY 'xxxx'; #初始化时root账号只有localhost
#开启远程登录
use mysql;
update user set host='%' where user='root';
flush privileges;

 

make install编译安装到指定目录
#--prefix指定安装的路径,组件文件统一存放,方便日后卸载删除
./configure --prefix=/usr/local/xxx

#-j 4指定并行编译任务数,适用多核CPU,一般配置为cpu核数的2倍
make -j 4 && make install

 


 

config/configure,make,make install
config,configure 会根据指定的相关参数,生成 Makefile,即自动化编译、构建脚本
如果指定 --prefix=(必须小写)安装目录,则生成的 Makefile 文件中预设 prefix(小写,与参数一致) 变量为指定的目录

make,根据 Makefile 完成编译和构建,生成可执行程序和相关库文件

make install,根据 Makefile 完成安装,其中包括 prefix 安装目录,
此时也可以指定 prefix 参数更换安装目录:make prefix= install(大小写与Makefile中变量一致)

有些组件如redis,源码包含 Makefile 文件,但没有 config/configure 脚本,同时 Makefile 中已经指定默认安装目录的变量为 PREFIX(大写),值为 /usr/local/,
所以在 make 编译构建后,make install 安装阶段,如果要调整安装目录,则需要指定 make PREFIX= install(必须大写)

总结:安装目录在 Makefile 中通过变量指定,而变量名可以通过 config/configure 脚本指定,最后在 make install 阶段调整安装目录的变量名大小写必须与 Makefile 中一致!

 


/bin,/sbin,/usr/bin,/usr/sbin区别
/bin : commandsin this dir are all system installed user commands   
系统预装系统程序,纯净系统中默认安装,所有用户都可以使用
例如:catcpdfgzipkilllsmkdirmorerm、tar等。

/sbin: commands in this dir are all system installed super user commands  
系统预装系统程序,纯净系统中默认安装,只有超级用户可以使用
例如:fdisk、ifconfig、 reboot、 shutdown等。    

/usr/bin: user commands for applications 
用户安装系统程序,纯净系统中非默认安装,所有用户都可以使用,后期安装
例如c++、g++、gccdufreegzipless、locale、makemanpasswd、wget等。

/usr/sbin:super user commands for applications 
用户安装系统程序,纯净系统中非默认安装,只有超级用户可以使用,后期安装
例如:dhcpd、httpd、netconfig、swap、tcpd、tcpdump等。 

/usr/local/bin
用户安装第三方程序,所有用户都可以使用
例如:MySQL

/usr/local/sbin
用户安装第三方程序,只有超级用户可以使用
例如:nginx

 

Linux中的某些重要的目录:
主目录:/root、/home/username
用户可执行文件:/bin、/usr/bin、/usr/local/bin
系统可执行文件:/sbin、/usr/sbin、/usr/local/sbin
其他挂载点:/media、/mnt
配置:/etc
临时文件:/tmp
内核和Bootloader:/boot
服务器数据:/var、/srv
系统信息:/proc、/sys
共享库:/lib、/usr/lib、/usr/local/lib

 


附录:Linux进程状态
D   不可中断睡眠 (通常是在IO操作) 收到信号不唤醒和不可运行, 进程必须等待直到有中断发生
R   正在运行或可运行(在运行队列排队中)
S   可中断睡眠 (休眠中, 受阻, 在等待某个条件的形成或接受到信号)
T   已停止的 进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行
W   正在换页(2.6.内核之前有效)
X   死进程 (未开启)
Z   僵尸进程  进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放BSD风格的
<   高优先级(not nice to other users)
N   低优先级(nice to other users)
L   页面锁定在内存(实时和定制的IO)
s   一个信息头
l   多线程(使用 CLONE_THREAD,像NPTL的pthreads的那样)
+   在前台进程组

 


 

 windows 路由表设置
语法:
route [-p] [command [destination] [mask netmask] [gateway] [metric] [if interface]

--添加临时路由
route add 10.29.8.10  mask 255.255.255.255  192.168.137.1

--删除临时路由
route delete 10.29.8.10  mask 255.255.255.255  192.168.137.1

--添加永久路由
route add -p 10.29.8.10  mask 255.255.255.255  192.168.137.1

--删除永久路由
route add -p 10.29.8.10  mask 255.255.255.255  192.168.137.1

 


MySQL命令行 \g 与 \G的作用
mysql> help(或 ?)

List of all MySQL commands:
ego       (\G) Send command to mysql server, display result vertically.
go        (\g) Send command to mysql server.

 

其中,\g 表示将命令提交到服务器执行,相当于SQL语句结尾的分号";",而 \G 表示将命令提交到服务器执行,但将结果垂直显示。
SQL语句以 \g 或 \G结尾,将不需要再输入结尾分号,否则,服务器会认为分号前没有命令要执行,报错:No query specified,如下
特别关注:\g 与 \G 为MySQL命令行工具专用,第三方工具如Navicat并没有实现其语法,所以无法使用。
mysql> select user,host from user where user='root'\g
+------+------+
| user | host |
+------+------+
| root | %    |
+------+------+
1 row in set (0.00 sec)


mysql> select user,host from user where user='root'\G
*************************** 1. row ***************************
user: root
host: %
1 row in set (0.00 sec)

mysql> select user,host from user where user='root'\G;
*************************** 1. row ***************************
user: root
host: %
1 row in set (0.00 sec)

ERROR: 
No query specified

 


MySQL单机性能测试

 


 

postman script
//请求结果保存
pm.test("get request", function () {
    if(pm.response.to.have.status(200))
    {
        var jsonData = pm.response.json();
        pm.environment.set("serial", jsonData["DeviceList"][0]["ID"]);
    }  
});

 

//MD5加密
var password = pm.environment.get("password");
var md5Password = CryptoJS.MD5(password).toString();
pm.environment.set("md5Password",md5Password);

 

//AES加密
const aesKey = CryptoJS.enc.Utf8.parse('this-is-aes-key')
// 加密函数
function encryptWithAES(word) {
  let srcs = CryptoJS.enc.Utf8.parse(word)
  let encrypted = CryptoJS.AES.encrypt(srcs, aesKey, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
  return encrypted.ciphertext.toString().toUpperCase()
}

// 原始请求体数据
var requestData = pm.request.body.raw;

// 加密请求体数据
var encryptedRequestData = encryptWithAES(requestData, aesKey);

// 更新请求体数据
pm.request.body.raw = {"param": encryptedRequestData};

console.log(pm.request.body.raw)

 


正向代理与反向代理

维基百科:
Unlike a forward proxy, 
which is an intermediary for its associated clients to contact any server, 
a reverse proxy is an intermediary for its associated servers to be contacted by any client。
翻译:
正向代理是【所要代理的客户端】与【其他所有服务器(重点:所有)】之间的代理者,
而反向代理是【其他所有客户端(重点:所有)】与【所要代理的服务器】之间的代理者。
正向与反向的概念,要从我们作为用户(客户端)的角度来看:
  • 一个对客户端(我们自己)负责,为正
  • 一个对所代理的服务器(我们的目标)负责,为反。
 
代理的对象不同,代理哪端便可以隐藏哪端:
  • 正向代理是代理我们发出请求的客户端,隐藏真实客户端(我们自己)
  • 反向代理是代理我们访问的服务器,隐藏真实服务端(我们的目标)

 


java执行java文件(语法:java ClassName,与class文件同目录),而非jar包(语法:java -jar something.jar)

1.编辑源文件如HelloWorld.java(java要求文件名与类名一致)
2.编译 javac HelloWorld.java,输出 HelloWorld.class
3.执行 java HelloWorld(类名,java会从当前目录class文件查找类的入口函数,但不能指定clsss文件名)

特别注意:环境变量 CLASSPATH 需要包括当前目录(.),示例如下
export JAVA_HOME=/usr/local/jdk1.8.0_181
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib:$CLASSPATH
export JAVA_PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin
export PATH=$PATH:${JAVA_PATH}

 


Linux设置时区方案
1./usr/share/zoneinfo/洲/国家 的时区文件拷贝或软连接到 /etc/localtime
2.tzselect,可视化依次选择 洲/国家(当前会话生效,重启后时效)
3.timedatectl set-timezone 洲/国家,CentOS7以上版本新增
特别注意:只有 timedatectl 可以同时更改系统时区、硬件时区、java虚拟机时区

java启动时指定时区
1.-Duser.timezone=Asia/Shanghai
2.-Duser.timezone=GMT+08
建议使用方案1,因为中国使用过夏令时,[Asia/Shanghai]可以兼容,而[MT+08]某些场景下会触发bug

 


docker镜像库加速(截至20230915验证正常,按照下载顺序排列)

cat > /etc/docker/daemon.json <<-EOF
{
    "registry-mirrors":["https://docker.mirrors.ustc.edu.cn","https://dockerproxy.com","http://hub-mirror.c.163.com","https://docker.m.daocloud.io"],
    "data-root":"/data/docker/"
}
EOF
systemctl daemon-reload && systemctl restart docker

 


docker 安装 mysqld_exporter
创建组件专用mysql账户
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'mysql_exporter'@'%' IDENTIFIED BY 'Mysql.exporter.123' WITH MAX_USER_CONNECTIONS 3;

 

不同版本启动命令有差异,具体版本范围暂未在官网确认,可以分别执行以下,然后 docker logs xxx查看是否相关配置文件报错
启动命令:新版本(2022以后肯定可以,2022之前不确定)
docker run -d \
  --name mysqld_exporter \
  --restart always \
  -p 9105:9104 \
  -e TZ=Asia/Shanghai \
  -v /etc/localtime:/etc/localtime \
  -v /usr/local/mysqld_exporter/my.cnf:/cfg/.my.cnf \
  prom/mysqld-exporter  --config.my-cnf=/cfg/.my.cnf

 

启动命令:老版本
docker run -d \
  --name mysqld_exporter \
  --restart always \
  -p 9105:9104 \
  -e TZ=Asia/Shanghai \
  -v /etc/localtime:/etc/localtime \
  -e DATA_SOURCE_NAME="user:pwd@(ip:port)/" \
  prom/mysqld-exporter

 

特别注意:
  1. 配置文件 /cfg/.my.cnf 为官方指定,所以需要通过虚拟路径挂载到本地路径,然后使用 --config.my-cnf 指定
  2. 服务端口号9104为官方指定,所以 -p 指定的内部端口号必须是9104
  3. 密码不能包含 #
 

grafana dashboard 模板 id
linux服务器监控:8919
mysql监控:7362
 

window bat
注释
  1. rem
  2. ::
 
清屏 cls
 
输出空行,以下10种方法,分为3组,每组效率递减
echo=
echo,
echo;

echo+
echo/
echo[
echo]

echo:
echo.
echo\

 

 > nul,不显示输出结果
echo hello world > nul

 

choice命令,用户从选择列表中选择一个选项,支持超时时间后自动选择
语法:CHOICE [/C choices] [/N] [/CS] [/T timeout /D choice] [/M text]
/C choices 指定要创建的选项列表。默认列表是 "YN"。此时命令行显示:【Y,N】
/N 在提示符中隐藏选项列表。提示信息依然显示。此时命令行不显示【Y,N】
/CS 允许选择分大小写的选项。在默认情况下,这个工具是不分大小写的。
/T timeout 做出默认选择之前,暂停的秒数。可接受的值是从 0到 9999。如果指定了 0,就不会有暂停,默认选项会得到选择。
/D choice 在 nnnn 秒之后指定默认选项。字符必须在用 /C 选项指定的一组选择中; 同时,必须用 /T 指定 nnnn。
/M text 指定提示之前要显示的消息。如果没有指定,工具只显示提示。此时命令行显示:text【Y,N】
 
特别注意:/D /T 可以用来实现延迟时间,结合 goto 语句,可以实现周期循环
 
set变量,以var为例 
1.参数为空,则设置字符串,变量与等号之间不能有空格,等号右边所有字符(包括空格)全部赋值给变量
SET [variable=[string]]
set var=1+1,则显示为“1+1”
 
2./a参数,则为计算器,表示等号后边是一个计算式,将结果赋值给变量
SET /A expression 
set /a var=1+1,则显示为“2”
 
3./p参数,则为用户输入,支持显示输入提示,可以和 < 输入重定向结合,从文件中获取变量值
SET /P variable=[promptString] 
set /p var=请输入变量值
 
if条件分支选择
if expression (statements1) ^
else if expression (statements2) ^
else (statements3)

 

注意,复合语句关键字之间不能换行,如 else 必须与上一句的 if 或 ) 在同一行(括号可以换行);
如果确实需要换行,则使用 ^ 号连接,表示换行输入
 
逻辑运算:批处理默认不支持多条件逻辑运算,如 and or && || 等,可以用以下方式实现
非:  if not expression
与:  (推荐)嵌套if  if expression1 (if expression2 (statements))
      省略括号if expression1 if expression2 (statements)(此时如果有else分支,则else就近匹配)  
      
或: (推荐)多个if对同一变量赋值(此时如果有else分支,请注意变量初始化,否则需要判断变量是否定义)
      嵌套if

 

使用场景
1、检测字符串(注意,用if检测字符串是否相等的时候,后面用的不是“=”,而是“==”):
@echo off
set str="this is a test"
REM 检测变量%str%是否等于test,如果相等,显示OK,否则显示NO
if "%str%"=="test" (echo OK) else echo NO
pause>nul

 

2、检测数值:(注意,批处理中大于符号不能用:“>”,而用"gtr",其它的也类似)
EQU - 等于
NEQ - 不等于
LSS - 小于
LEQ - 小于或等于
GTR - 大于
GEQ - 大于或等于

 

3、if可以用来检测某个变量是否已经被定义
@echo off
set str1="ok"
set str2="no"
if defined str1 echo str1已经被定义
if defined str2 echo str2已经被定义
if defined str3 (echo str3已经被定义) else echo str3 没有被定义
pause>nul

 

4、if结合errorlevel使用:
说明:环境变量errorlevel的初始值为0,当一些命令执行不成功,就会返回一个数值,如:1 ,2 等
IF ERRORLEVEL 是用来测试它的上一个DOS命令的返回值的,注意只是上一个命令的返回值,而且返回值必须依照从大到小顺序判断。
@ECHO OFF 
XCOPY F:\test.bat D:\ 
IF ERRORLEVEL 1 ECHO 文件拷贝失败 
IF ERRORLEVEL 0 ECHO 成功拷贝文件 
以上,不能先判断0,后判断1

 


 windows bat 变量延迟

“变量延迟”是批处理中一个十分重要的机制,它因预处理机制而生,用于复合语句,特别是大量使用于强大的for语句中。只有熟练地使用这一机制,才能在for的世界中如鱼得水,让自己的批处理水平更上一层楼。很多时候,对for的处理机制,我们一直是雾里看花,即使偶有所得,也只是只可意会难以言传。很多细节上的经验,是只有通过大量的摸索才能得到的。
 
变量延迟摘要:
  1. 为什么要使用变量延迟?
    1. 因为要让复合语句内部的变量实时感知到变量值的变化。
  2. 在哪些场合需要使用变量延迟语句?
    1. 在复合语句内部,如果某个变量的值发生了改变,并且改变后的值需要在复合语句内部的其他地方被用到,那么,就需要使用变量延迟语句。
  3. 怎样使用变量延迟?
    1. 使用 setlocal enabledelayedexpansion 语句:
      1. 在获取变化的变量值语句之前使用setlocal enabledelayedexpansion,并把原本使用百分号对闭合的变量引用改为使用感叹号对来闭合,即 !var!
    2. 使用 call 语句:
      1. 在原来命令的前部加上 call 命令,并把变量引用的单层百分号对改为双层百分号,即 %%var%%
 
批处理的执行过程
“自上而下,逐条执行”。
 
“逐条”并不等同于“逐行”
这个“条”,是“一条完整的语句”的意思,并不是指“一行代码”。
在批处理中,是不是一条完整的语句,并不是以行来论的,而是要看它的作用范围。
 
什么样的语句才算“一条完整的语句”
  1. 在复合语句中,整个复合语句是一条完整的语句,而无论这个复合语句占用了多少行的位置,常见的复合语句有
    1. for语句
    2. if……else语句
    3. 用 连接符&、||和&&连接的语句
    4. 用管道符号|连接的语句
    5. 用括号括起来的,由多条语句组合而成的语句块;
  2. 在非复合语句中,如果该语句占据了一行的位置,则该行代码为一条完整的语句。
  
下面的代码共有14行,但是只有完整的语句只有7条,它们分别是:
  第1条:第1行的echo语句;
  第2条:第2行的set语句;
  第3条:第3、4、5、6行上的for复合语句;
  第4条:第7行的echo语句;
  第5条:第8、9、10行上用&&和||连接的复合语句;
  第6条:第11、12、13行上的if……else复合语句;
  第7条:第14行上的pause语句。
 
@echo off
set num=0
for /f %%i in ('dir /a-d /b *.exe') do (
    set /a num+=1
    echo num 当前的值是 %num%
)
echo 当前目录下共有 %num% 个exe文件
dir /a-d /b *.txt|findstr "test">nul&&(
    echo 存在含有 test 字符串的文本本件
) || echo 不存在含有 test 字符串的文本文件
if exist test.ini (
    echo 存在 test.ini 文件
) else echo 不存在 test.ini 文件
pause

 

预处理机制
在代码“逐条”执行的过程中,cmd.exe这个批处理解释器会对每条语句做一些预处理工作,这就是批处理中大名鼎鼎的“预处理机制”。
 
预处理的大致情形是这样的:
  1. 首先,把一条完整的语句读入内存中(不管这条语句有多少行,它们都会被一起读入),
  2. 然后,识别出哪些部分是命令关键字,哪些是开关、哪些是参数,哪些是变量引用……
  3. 如果代码语法有误,则给出错误提示或退出批处理环境;
  4. 如果顺利通过,接下来,就把该条语句中所有被引用的变量及变量两边的百分号对,用这条语句被读入内存之就已经赋予该变量的具体值来替换……
  5. 当所有的预处理工作完成之后,批处理才会执行每条完整语句内部每个命令的原有功能。
 
也就是说,如果命令语句中含有变量引用(变量及紧邻它左右的百分号对),并且某个变量的值在命令的执行过程中被改变了,即使该条语句内部的其他地方也用到了这个变量,也不会用最新的值去替换它们,因为某条语句在被预处理的时候,所有的变量引用都已经被替换成字符串常量了,变量值在复合语句内部被改变,不会影响到语句内部的其他任何地方。
 
预处理说明
set num=0&&echo %num%
是一条复合语句,它的含义是:把0赋予变量num,成功后,显示变量num的值。

 

虽然是在变量num被赋值成功后才显示变量num的值,但是,因为这是一条复合语句,在预处理的时候,&&后的%num%只能被set语句之前的语句赋予变量num的具体值来替换,而不能被复合语句内部、&&之前的set语句对num所赋予的值来替换,可见,此num非彼num。
 
变量生效方案之变量延迟扩展,保留符合语句功能
“变量扩展”:用具体的值去替换被引用的变量及紧贴在它左右的那对百分号。
对这段代码适用的办法是:使用变量延迟扩展语句,让变量的扩展行为延迟一下,从而获取我们想要的值。
 
一般说来,延迟变量的扩展行为,可以有如下选择:
  1. 在适当位置使用 setlocal enabledelayedexpansion 语句;
  2. 在适当的位置使用 call 语句。
 
变量生效方案之拆分复合语句,不兼容复合语句
把用&&连接复合语句拆分为两条单独的语句,
set num=0
echo %num%

 


 

 
posted on 2023-09-15 16:00  xiaoyaozhe  阅读(310)  评论(0编辑  收藏  举报