本文记录 Linux 常用命令记录。<>
为必填,[]
为可选,()
为注释性文字。
注:命令一般没有系统之分,但经常在ubuntu中测试,偶尔也在Centos测试。
查找系统体积最大的文件
1 | find / -type f -print0 2>/dev/null | xargs -0 du -h 2>/dev/null | sort -rh | head -n 10 |
注:先用find查找(可指定目录),用排序,选中最大的N个。
1 | find / -name "..." 2>&1 | grep -v "Permission denied" |
查找替换
仅查看当前目录所有.cpp和.c文件:
1 | find ./ -maxdepth 1 -name '*.cpp' -or -name '*.c' |
注:使用-maxdepth 1指定搜索的目录深度。去掉的话,则是递归搜索所有子目录。
find的几种方法:
1 | find ./ -name "*[*.h|.c|.cpp]" # 注:这种形式会匹配到.sh |
主要利用 sed 命令,注意,如果只打印到终端,去掉-i
选项。
将当前目录所有文件的intMAX字符串替换为INT_MAX:
1 | sed -i 's/intMAX/INT_MAX/g' `grep intMAX ./ -rl` |
注:可以修改grep查找路径来指定目录。
注:grep -l可查看匹配的文件名。-n可显示出匹配的行号。
1 | sed -i 's/ExecStart.*/ExecStart=\/usr\/bin\/dockerd -H fd:\/\/ --graph \/mnt\/docker/g' docker.service |
将docker.service文件ExecStart那一行替换为ExecStart=/usr/bin/dockerd -H fd:// --graph /mnt/docker
。注意,路径的/
需要转义,即\/
。添加-i可替换原文件
将当前日期作为版本号:
1 | verdate="`date +%y%m%d`" |
注意,sed 中使用变量,需要用双引号。如果其中还有双引号,需要\
转义。
参数cloudhub如存在,则替换 .env 文件对应的值,可输入类似 IP 地址的格式。
1 | [[ ! -z $cloudhub ]] && sed -i "/CLOUDHUB=/c\CLOUDHUB=${cloudhub}" .env && echo "set cloudhub success" |
删除某个指定的字符串,此处为"LATLEE".
(注意双引号和点号):
1 | sed -i 's/"LATLEE".//g' foo.txt |
代码格式化
去掉行尾多余空格
1 | sed -i "s/[ ]*$//g" test.cpp |
将tab键替换为4个空格
1 | sed -i "s/\t/ /g" test.cpp |
注:/t与/g之间有4个空格,表示替换为4个空格。
一个比较完整的脚本内容如下:
1 | #!/bin/bash |
统计代码数量
统计当前目录所有.h .cpp文件文件行数(其它类型类推):
1 | find . ! -name "." -name "*[.h|.hpp|.c|.cpp]"|xargs cat|grep -v ^$|wc -l |
统计当前目录.cpp文件个数
1 | find . ! -name "." -name "*[.h|.hpp|.c|.cpp]"|wc -l |
遗留:.h会匹配.sh文件,.c会匹配.cpp文件。
程序后台执行
有时需要在本地使用ssh连接到linux上执行命令或程序,但当连接断开时(断网或本机关机),程序会退出,使用nohup可以将程序放到后台执行,并且不随外界影响,当然,自身系统挂掉除外。示例:
1 | nohup xxx & >> /tmp/output.txt |
注:执行命令后,要用exit退出终端,否则意外断开连接时,程序会自动退出。
查找文件指定字符串出现第一次或最后一次位置
查找指定文件某字符串第一次出现位置:
命令:cat <文件名称> | grep -n "<字符串>" | head -n 1
示例:
1 | cat log.txt | grep -n "MISCONF Redis is configured to save RDB snapshots" | head -n 1 |
查找指定文件某字符串最后一次出现位置:
命令:cat <文件名称> | grep -n "<字符串>" | tail -n 1
示例:
1 | cat log.txt | grep -n "MISCONF Redis is configured to save RDB snapshots" | tail -n 1 |
解释:
先用cat命令查看文件内容,接着用grep搜索指定的字符串,注意要添加”-n”选项以便显示匹配字符串在文件中的行号,最后用head或tail显示查找到的内容的开头部分或结尾部分字符串,”-n 1”表示只显示一行,故能实现显示第一次或最后一次字符串。打开文件(notepad++或vs code使用ctrl+g快捷键)定位到行号即可。综上,使用管道可实现目的。
ls排序
默认:按字符升序,注:如文件名为1、2、10、20,排序后变成1、10、2、20
按时间:
ls -lt # 时间新的,排在前面,对比:ls -l、ls -lt
ls -ltr # 时间新的,排在后面
按大小排序:
ls -Slh # 由大到小,h表示以K、M、G单位显示
ls -Srlh # 由小到大,即文件体积大的在后面,在文件数量多时建议使用
截取文件指定行数
背景:日志文件体积太庞大,需要截取A行到B行之间的内容。
命令:sed -n 'A,Bp' foo.txt >> output.txt
示例,截取foo.txt文件第100行到200行:sed -n '100, 200p' foo.txt >> output.txt
其它使用:通过指定行号,用此命令将大文件分割为小文件。
扩展:根据指定字符或条件来截取(如大括号,时间戳),似乎太复杂。
注意:传入 shell 变量时,需要使用双引号,单引号无法解析变量值。
分割文件
背景:文件太大(如GB级别),一般编辑器打不开,需要分割之。
命令:split -a <后缀个数> -d(后缀为数字) -b <每个文件的容量> -l <每个文件行数> <要分割的文件> [分割后文件前缀]
示例:后缀为4个数字,按1MB分割,默认前缀为x
:split -a 4 -d -b 1M aaa.txt
。
后缀为4个数字,按1万行分割,前缀为test
:split -a 4 -d -l 10000 aaa.txt test
。
遗留:似乎无法指定后缀
NOTE:如果要合并,则使用cat * > a.txt
,不过似乎不好指定顺序。
在指定行数追加字符串
如:在 a.txt 的第10行后面插入 COMMIT;
。
1 | sed -i '10a\COMMIT;' ver.sql |
目的:每隔1万行插入COMMIT;
,使用 shell 获取行号,但用上面语句失败。转换思路:
先按1万行分割,得到 x 开头的文件(注:此时没有后缀),在文件末追加字符串,再合并。
1 | #!/bin/bash |
使用read进行命令行交互
背景:使用脚本安装软件,有些目录需要确认,使用read等待用户输入信息。
1 | echo "Is this ok? [Y]/n" |
打包压缩指定大小
背景:github单个文件体积要小于100MB,过大无法上传,需要分割。(其它场合亦然)
命令分解:先解压,再分割。
1 | tar jcf arm-unknown-linux-gnueabihf.tar.bz2 arm-unknown-linux-gnueabihf/ |
查看oom得分
1 | #!/bin/bash |
一条命令定时执行
查看某个进程的信息,循环N次。注:理论上应该死循环的,先用for
1 | for i in {1..10000}; do ps aux | grep mytest; sleep 1; done |
拷贝时忽略子目录
拷贝test目录到aaa目录,忽略test的downloads和output:
1 | cd test |
注:忽略多个目录,需要用 –exclude 。目标目录不存在会自动创建。
查找忽略指定目录
1 | find ./ -name '*.cpp' -or -name '*.c' -not -path '**/11.serialport_linux/**' ! -path "*/*socket*/*" |
注:似乎直接指定目录无效果,前后要添加*
,not
和!
等效。多个目录要分别指定。
查看cpu核心数量
1 | cat /proc/cpuinfo | grep processor | wc -l |
查看已删除的文件占用的进程(?如何描述)
1 | lsof | grep delete |
service操作
1 | vi /etc/systemd/system/edgecore.service |
用indent代码格式化
查找某目录下所有源码,转换成linux格式,再格式化。
1 | find ./ -name '*.cpp' -or -name '*.c' -or -name "*.h" | xargs dos2unix |
临时
关于PID,如果在终端执行程序A,A的父进程为bash(或sh),因为是终端启动的。如果A创建子进程B,B的父进程为A,如果A创建B后自行退出,则B的父进程为1(由init接管)。如果在B中kill掉A,则A、B同时退出。
windows 重定向:
1 | ./foo 1>a.txt 2>&1 |
注:界面不显示信息,待改
shell 脚本参数截取
目的:从第N个参数开始遍历。相当于前N个固定,后N个不固定,如IP地址列表。
1 | # 从第3个开始 |
root密码输入
问题:linux输入密码不回显,有时不清楚输入了什么内容。如果多次尝试失败,系统可能会拒绝登录。可以在命令行显式指定密码。eg:
1 | echo "123456" | sudo -S ls # 先指定密码,如果正确,再切换。 |
字符串截取
总则:使用${xxx}
形式截取。
1 | var=https://latelee.org/foo.html |
字符串补齐
1 | i=0 |
与 C 语言的 printf 类似
shell 时间计算。支持 minute、hour,默认为时间后,时间前使用 ago,以下为当前时间前后:
1 | time1=$(date -d "10 minute ago" +"%Y-%m-%d %H:%M:%S") |
查看动态库函数名称
1 | nm libfoo.so | awk '{print $3}' | c++filt.exe | tee cfunc.txt |
先查动态库的函数名,过滤得到第3列(真正函数名),去掉c++修饰,保存文件。
C++函数名去掉装饰(mangled、demangled)
压缩包添加密码
1 | zip -q -r -P 123456 foo.zip foo |
注:不同时间压缩的zip文件,其二进制可能会不同(计算md5会有差异),因其考虑了文件访问时间。保存二进制相同,使用:
1 | zip -qr -X -D foo.zip foo |
根据偏移量定位文件
以 txt 文件为例,先用 hexdump 输出到指定文件,如:
1 | hexdump foo.out -C > a.txt |
根据 a.txt 中的偏移地址计算即可。该文件示例:
1 | 00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| |
清缓存
1 | sudo -s |
停止指定进程
停掉包含demo-0.0.1
的进程:
1 | kill $(ps aux | grep demo-0.0.1 | grep -v "grep" | tr -s ' '| cut -d ' ' -f 2) |
获取某个运行的进程信息,并 kill 掉,一行 shell :
1 | [[ $(ps aux | grep demo*.jar | grep -v 'grep' | awk '{print $2;}') != "" ]] && kill -9 $(ps aux | grep demo*.jar | grep -v 'grep' | awk '{print $2;}') |
注:如果使用 if 判断的话,当不存在进程时会报语法错误,故只用一行shell解决。
修改字符集
1 | localectl set-locale LANG=en_US.UTF-8 |
加密压缩解压
对当前 workshop目录加密压缩并解压,密码为123456。
1 | tar -cjf - workshop | openssl des3 -salt -k 123456 -out workshop.tar.bz2 |