Linux常用命令使用笔记
随机记录一些Linux常用命令使用笔记。
rsync:文件同步
rsync 来源 目标 --archive --acls --xattrs --verbose --progress --one-file-system
需要同步并删除时,加--delete
参数
输出重定向
终端默认打开3个fd:
- 0:标准输入
- 1:标准输出
- 2:标准错误
>dev/null 2>&1
:输出重定向到null,错误重定向到输出(此时输出是null,所以错误输出到了null),不打印输出和错误
2>&1 >/dev/null
:错误重定向到输出(此时输出是终端,所以错误输出到了终端上打印),输出重定向到null,只打印错误
2>&-
:关闭标准错误描述符。The general form of this one is M>&-
, where "M" is a file descriptor number. This will close output for whichever file descriptor is referenced, i.e. "M".
2>/dev/null
:The general form of this one is M>/dev/null
, where "M" is a file descriptor number. This will redirect the file descriptor, "M", to /dev/null
.
2>&1
:The general form of this one is M>&N
, where "M" & "N" are file descriptor numbers. It combines the output of file descriptors "M" and "N" into a single stream.
|&
:This is just an abbreviation for 2>&1 |
. It was added in Bash 4.
&>/dev/null
:This is just an abbreviation for >/dev/null 2>&1
. It redirects file descriptor 2 (STDERR) and descriptor 1 (STDOUT) to /dev/null
.
>/dev/null
:This is just an abbreviation for 1>/dev/null
. It redirects file descriptor 1 (STDOUT) to /dev/null
.
screen/tmux
如何将进程移到screen/tmux:
- Ctrl+Z进程
- bg恢复进程在后台运行
- 解除从属关系disown %1
- 启动一个screen/tmux
- 查找进程PID
- 执行reptyr -T pid,将进程移到该screen/tmux
disown 命令: https://gnu-linux.readthedocs.io/zh/latest/Chapter06/sshBackstage.html
SSH连接后自动打开Tmux,同时避免与VSCode远程开发冲突 https://zhuanlan.zhihu.com/p/346594276
tmux new -s 7580:创建会话名称为7580的会话,最好不要纯数字名称 ./umbuild_7580.sh > stdout.txt 2>&1 &:后台执行编译程序 tmux detach:会话分离
tmux ls:列出会话列表 tmux attach -t 【会话编号/会话名称】:重新进入会话 jobs
- Done:后台程序执行完成
- Running:表示正在运行
- Stopped:表示已经被挂起,那么不再会被调度,查看下编译输出,可能已经error了
- kill %job-id
- fg %job
- bg %jog,一般终端会一直输出,一般使用快捷键Ctrl+Z
该方法可以保证编译不因为网络断开而终止 当关闭ssh窗口后重新连接,虽然无法重新进入会话,但可以通过tail stdout.txt查看最新编译进展,编译成功后stdout.txt最后一行会为0
diff命令:比较目录/文件差异
对比2个目录有哪些文件不一样,从diff手册页:
-q
仅报告文件是否不同,而不是差异的细节。
-r
比较目录时,递归比较找到的所有子目录。
示例命令:
diff -qr dir1 dir2
cp命令
当需要拷贝多个文件并且需要保留源文件的目录树结构时, 如果源目录的文件比较纯净,没有其他相关的文件或目录时, 我们只需要执行
cp -r [src_dir] [dst_dir]
否则,只能执行
cp --parent [src_file] [dst_dir]
sudo命令执行很慢
1、首先如果当用登录的用户名不在"/etc/sudoers"文件中,是不能执行sudo命令的。可以用root身份手动修该文件,把当前登录用户名加入该文件中。
2、用"hostname "命令查看当前主机的主机名称。例如,该命令返回"ubuntu ".
3、用vi打开"/etc/hosts"文件,并将"ubuntu"加入到 "127.0.0.1"这行中。
例如:
127.0.0.1 localhost ubuntu
原因是sudo认证时,pam的代码会访问到域名服务器,如果你的hostname不被/etc/hosts记录,且/etc/resolv.conf里的域名服务器无法正确解析你的hostname,将会导致挂起30秒。
https://bugzilla.redhat.com/show_bug.cgi?id=479464
https://superuser.com/questions/429790/sudo-command-trying-to-search-for-hostname
https://askubuntu.com/questions/322514/terminal-command-with-sudo-takes-a-long-time/458057#458057
sshpass命令:ssh自动输入密码
sudo apt install sshpass
# quick ssh connect
alias pon1='sshpass -p "pon_123" ssh um_pon@192.168.133.22'
alias pon2='sshpass -p "ztc@321n" ssh gztc@192.168.133.22'
cut命令
cut 命令对指定文件的内容的每一行进行截断,并将截断后的所有内容(或部分内容)输出到标准输出。
usage: cut -b list [-n] [file ...]
cut -c list [file ...]
cut -f list [-s] [-d delim] [file ...]
如果不指定 File,cut 命令将读取标准输入。必须指定 -b、-c 或 -f 标志之一。
参数:
- -b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。(注意:一个空格算一个字节,一个汉字算三个字节)
- -c :以字符为单位进行分割。(中文字符和空格都算一个字符)
- -d :自定义分隔符,默认为制表符。
- -f :与
-d
一起使用,指定显示哪个区域。 - -n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的范围之内,该字符将被写出;否则,该字符将被排除
dd:磁盘读写命令
通过dd生成指定内容的文件
在某些情况下,可能会用到全为某个值的 bin 文件,可使用 dd 命令配合 /dev/zero 这个特殊的文件设备,来生成全为 0x00 的 bin 文件,而后在使用 tr 命令,替换0x00 为 0xFF,命令如下所示:
dd if=/dev/zero bs=1M count=2 | tr "\000" "\377" > test.bin
命令生成全为 0xFF 的 2MB 的 bin 文件。 其中 \377
为八进制数,即 0xFF。
在生成 test.bin 文件后,使用命令:
echo hello | dd bs=512 seek=2 conv=notrunc of=test.bin
可将 hello 写入到 test.bin 文件的 0x400 地址处,文件大小不变。 使用命令查看:
hexdump test.bin -n 100 -s 1008 -C
在新生成的 test.bin 中,从 0x200 地址开始,截取 2K 文件,生成 test1.bin 文件:
dd if=test.bin conv=notrunc bs=512 skip=1 count=4 of=test1.bin
- dd命令可以轻易实现创建指定大小的文件,如
dd if=/dev/zero of=test bs=1M count=1000
在当前目录下会生成一个1000M的test文件,文件内容为全0(因从/dev/zero中读取,/dev/zero为0源),但是这样为实际写入硬盘,文件产生速度取决于硬盘读写速度,如果欲产生超大文件,速度很慢。在某种场景下,我们只想让文件系统认为存在一个超大文件在此,但是并不实际写入硬盘
则可以
dd if=/dev/zero of=test bs=1M count=0 seek=100000
此时创建的文件在文件系统中的显示大小为100000MB,但是并不实际占用block,因此创建速度与内存速度相当,seek的作用是跳过输出文件中指定大小的部分,这就达到了创建大文件,但是并不实际写入的目的。当然,因为不实际写入硬盘,所以你在容量只有10G的硬盘上创建100G的此类文件都是可以的。
- 随机生成1百万个1K的文件 seq 1000000 | xargs -i dd if=/dev/zero of={}.dat bs=1024 count=1
使用dd进行磁盘读写速度测试
一般情况下,我们都是使用dd命令创建一个大文件来测试磁盘的读写速度。但是,很多人都存在一个误区,以为dd命令显示的速度就是磁盘的写入速度,其实这是不然的。我们分析一下dd命令是如何工作的。
- dd if=/dev/zero of=/xiaohan/test.iso bs=1024M count=1
这种情况下测试显示的速度是dd命令将数据写入到内存缓冲区中的速度,只有当数据写入内存缓冲区完成后,才开始将数据刷入硬盘,所以这时候的数据是无法正确衡量磁盘写入速度的。
- dd if=/dev/zero of=/xiaohan/test.iso bs=1024M count=1;sync
这种情况下测试显示的跟上一种情况是一样的,两个命令是先后执行的,当sync开始执行的时候,dd命令已经将速度信息打印到了屏幕上,仍然无法显示从内存写硬盘时的真正速度。
- dd if=/dev/zero of=/xiaohan/test.iso bs=1024M count=1 conv=fdatasync
这种情况加入这个参数后,dd命令执行到最后会真正执行一次“同步(sync)”操作,所以这时候你得到的是读取这128M数据到内存并写入到磁盘上所需的时间,这样算出来的时间才是比较符合实际的。
- dd if=/dev/zero of=/xiaohan/test.iso bs=1024M count=1 oflag=dsync
这种情况下,dd在执行时每次都会进行同步写入操作。也就是说,这条命令每次读取1M后就要先把这1M写入磁盘,然后再读取下面这1M,一共重复128次。这可能是最慢的一种方式,基本上没有用到写缓存(write cache)。
总结:
建议使用测试写速度的方式为:
dd if=/dev/zero of=/xiaohan/test.iso bs=1024M count=1 conv=fdatasync
建议使用测试读速度的方式为:
dd if=/xiaohan/test.iso of=/dev/zero bs=1024M count=1 iflag=direct
*注:要正确测试磁盘读写能力,建议测试文件的大小要远远大于内存的容量!!!
curl命令
curl使用指定ip请求https
一般地,在 curl 中,如果想以指定的 ip 来请求一个域名地,可以使用 curl http://127.0.0.1/example -H 'Host: www.example.org'
这种指定 Host 头的做法,但这在 https 中可能会失败,显示 no alternative certificate subject name matches target host name '127.0.0.1
。
显然这是由于 curl 将 https://127.0.0.1
里的 127.0.0.1
而不是 Host 头用于验证证书的 subject name,而这个 ip 如果不在证书的 subject names 中,
将会导致证书验证失败。
一般的解决方案,我们可以在 /etc/hosts
或 dnsmasq 用指定 ip 解析这个域名,但这改起来显示比较繁琐。还好在 curl 7.21.3 中,提供了一个 --resolve <host:port:address>'
的
参数,让我们可以很方便地将域名解析到指定的 ip 上,例如上面的请求可以改成 curl --resolve 'www.example.org:443:127.0.0.1' https://www.example.org
。
curl 有一个 --resolve 参数可以达到类似于 hosts 文件的效果。用 -H 来指定 Host 的话,在 https 请求时要记得配合 -k / —insecure 绕过域名检查。
Linux 中使用 curl 代替 telnet 测试端口是否连通curl
在一些没有装有telnet
的机器并且还没有访问外网的权限下,想要测试内网某个ip
下的端口是否可以被连接,可以使用curl telnet://
curl -vv telnet://192.168.1.101:8080
显示Connected
表示可以连接,使用Ctrl+C
退出。
$ curl -vv telnet://192.168.1.101:8080
* About to connect() to 192.168.1.101 port 8080 (#0)
* Trying 192.168.1.101...
* Connected to 192.168.1.101 (192.168.1.101) port 8080 (#0)
一直显示Trying
表示连接不通,使用Ctrl+C
退出。
$ curl -vv telnet://www.baidu.com:443
* About to connect() to www.baidu.com port 443 (#0)
* Trying 112.80.248.75...
curl杂项
curl不关闭打印信息时会另起进程
curl命令去除所有的状态信息:curl -s [URL] -o [path]
curl命令不使用缓存:curl -H 'Cache-Control: no-cache' http://www.example.com
模拟post请求: curl -H "Content-Type: application/json; charset=utf-8" -X POST -d '{"jsonrpc":"2.0","method":"hgmanager.STBSNAndMAC","params":{"mac":"00:19:F0:FF:FD:36","sn":"009901FF0018100000010019F0FFFD36"}}' 192.168.1.1:61998
使用 curl 上传一张图片:
curl -X POST -d "smfile=/Users/ashfinal/2.png" https://sm.ms/api/upload
指定 curl 的 UA:
curl --user-agent "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36" https://www.bing.com/az/hprichbg/rb/BMXTunnel_ZH-CN11405649743_1920x1080.jpg -O
curl (可直接发送格式化请求例如json),提交json数据需要加header,否则需 'json={"phone":"13521389587","password":"test"}’
curl -H "Content-type: application/json" -X POST -d '{"phone":"13521389587","password":"test"}' http://domain/apis/users.json
普通请求:curl $URL -d "2880[]=105&pid=2880&p=最佳&count=1&receipt=1&poll=投票"
请求 GitHub Trend 数据
curl -G https://api.github.com/search/repositories --data-urlencode "sort=stars" --data-urlencode "order=desc" --data-urlencode "q=language:java" --data-urlencode "q=created:>`date -v-7d '+%Y-%m-%d'`" > tmp.json
curl和bash
https://www.idontplaydarts.com/2016/04/detecting-curl-pipe-bash-server-side/
使用 curl | bash
是不安全的,bash如果执行过程中有延时,会被服务端检测到,从而发送恶意数据。
# 简单辨别:服务端的延时检测不一定是3秒,也不一定只检测一次,所以还是不能 curl | bash
curl https://example.com/setup.bash | cat
curl https://example.com/setup.bash | (sleep 3; cat)
wget命令
wget关闭进度输出:
wget -q [URL] -O [path]
wget --header="Cache-Control: no-cache"
wget -o log
wget发post请求:wget --post-data="user=user1&pass=pass1&submit=Login" http://domain.com/path/page_need_login.php
crontab:设置定时任务
cron语法
crontab修改编辑器
方法一:通过select-editor 使用 select-editor 命令,随便选一个编辑器,然后在home目录将生成一个 .selected_editor 文件
# Generated by /usr/bin/select-editor
# SELECTED_EDITOR="/usr/bin/vim.tiny" SELECTED_EDITOR="/usr/bin/nvim"
修改该文件即可
方法二:通过环境变量 环境变量可以设置VISUAL
和EDITOR
,两个任何一个都可以,如我想在编辑crontab时使用vim打开可以这么做
VISUAL=vim crontab -e
或者也可以这样
EDITOR=vim crontab -e
当然,你也可以添加到/etc/profile
里,这样每次使用crontab前不需要再声明环境变量了
export EDITOR=vim
export VISUAL=vim
dig:DNS查询
Dig是一个在类Unix命令行模式下查询DNS包括NS记录,A记录,MX记录等相关信息的工具。
dig github.com @8.8.8.8
du:统计目录/文件占用磁盘大小
du -sh
-s,--summarize:display only a total for each argument, -s这个参数的作用就是仅显示总计,即当前文件夹的大小。
-h, --human-readable:print sizes in human readable format (e.g., 1K 234M 2G)
-c, --total:produce a grand total,使用-c选项,你可以在输出的最后一行看到总的磁盘使用情况,包括所有子目录
[modao@modao qemu]$ du -shc
7.5G .
7.5G total
[modao@modao qemu]$ du -sh
7.5G .
du -sh * *
可以将当前目录下所有文件的大小给列出来
要将这些列出来的文件按照从大到小的方式排序:du -s * | sort -nr,排序时不能加-h参数,否则排序结果可能不对
df:查看磁盘使用情况
df -h
grep:检索文件内容
遇到的问题:
用grep -c “xxx字符”得到的是行数,如果一行中有多个匹配到的字符,只会算作一个
解决方法:
使用grep -o "xxx字符"按行显示出所有的匹配结果,然后再用grep -c "xxx字符"来计算行
grep字符串全匹配:grep -w
grep命令查找多个字符串:grep -E 'pattern1|pattern2' file
linux下使用grep在当前目录下搜索所有文件中含有的字符串:grep -r [搜索内容]
kill:杀进程
kill -9 pid
可以使用其它信号,一般用9,代表结束进程
killall pid_name
pid:可能选择有以下四种
- pid大于零时,pid是信号欲送往的进程的标识。
- pid等于零时,信号将送往所有与调用kill()的那个进程属同一个使用组的进程。
- pid等于-1时,信号将送往所有调用进程有权给其发送信号的进程,除了进程1(init)。
- pid小于-1时,信号将送往以-pid为组标识的进程。
当需要把 linux 下符合某一项条件的所有进程 kill 掉,又不能用 killall 直接杀掉某一进程名称包含的所有运行中进程(我们可能只需要杀掉其中的某一类或运行指定参数命令的进程),这个时候我们需要运用 ps, grep, cut 和 kill 一起操作。
杀掉所有含有关键字"stress"的进程:
ps -ef | grep stress | grep -v grep | cut -c 9-15 | xargs kill -9
- "ps -ef" 是linux里查看所有进程的命令。这时检索出的进程将作为下一条命令"grep stress"的输入
- "grep stress" 的输出结果是,所有含有关键字"stress"的进程
- "grep -v grep" 是在列出的进程中去除含有关键字"grep"的进程
- "cut -c 9-15" 是截取输入行的第9个字符到第15个字符,而这正好是进程号PID
- "xargs kill -9" 中的 xargs 命令是用来把前面命令的输出结果(PID)作为"kill -9"命令的参数,并执行该命令。"kill -9"会强行杀掉指定进程。
另一种方法,使用awk
ps x | grep gas | grep -v grep | awk '{print $1}' | xargs kill -9
驱动模块相关命令
insmod:加载驱动
modprobe:加载驱动,并自动加载依赖驱动
rmmod:卸载驱动
lsmod:查看系统中所有已经被加载了的所有的模块以及模块间的依赖关系,可能还可以看驱动大小
modinfo:获得模块的信息
cat /proc/modules:能够显示驱动模块大小、在内核空间中的地址
cat /proc/devices:只显示驱动的主设备号,且是分类显示
/sys/modules:下面存在对应的驱动的目录,目录下包含驱动的分段信息等等。
ls /sys/bus
ls /dev
tree:打印目录结构
tree命令生成目录结构保存为 html:tree -H . > test.html
方便生成目录
tree --charset utf8 -H file:///Users/ashfinal/Downloads ~/Downloads -o ~/tmp.html
strip:去除可执行文件的符号表
strip:简单的说就是给文件脱掉外衣,具体就是从特定文件中剥掉一些符号信息和调试信息,使文件变小。
对一个可执行文件,可以使用file查看其基本信息,可以使用nm查看其符号信息。
使用strip对可执行文件处理后,文件大小会变小,nm查看不到符号信息。
strip不仅仅可以针对可执行文件, 还能针对目标文件和动态库等。在实际的开发中,经常需要对动态库.so进行strip操作,减少占地空间。 而在调试的时候(比如用addr2line),就需要符号了。 因此,通常的做法是:strip前的库用来调试,strip后的库用来实际发布,他们两者有对应关系。一旦发布的strip后的库出了问题,就可以找对应的未strip的库来定位。
ps:查看进程
相关进程状态:
D 不可中断,Uninterruptible sleep (usually IO) R 正在运行,或在队列中的进程 S 处于休眠状态 T 停止或被追踪 Z 僵尸进程 W 进入内存交换(从内核2.6开始无效) X 死掉的进程 < 高优先级 N 低优先级 L 有些页被锁进内存 s 包含子进程 + 位于后台的进程组; l 多线程,克隆线程multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
mount:文件系统挂载命令
查看系统挂载情况:
- cat /proc/mounts
- mount
修改/etc/fstab 默认挂载权限
mount -a:根据fstab挂载文件系统
重新挂载根目录,加读写权限 mount -o remount rw /
ping:发icmp包判断网络是否可达
-i <间隔秒数> 指定收发信息的间隔时间。
-c <完成次数> 设置完成要求回应的次数。
-I <网卡接口> 使用指定的网络接口送出数据包。
-q 不显示指令执行过程,开头和结尾的相关信息除外。
-v 详细显示指令的执行过程。
-w -W -c是指定总的发包数,-w是指定总的发包时间 ping -i 0.2 baidu.com ping: cannot flood; minimal interval allowed for user is 200ms 如果要使用0.1s,则需要以root用户身份运行 普通ping,在用-c指定包数为1时,且在目标不可达时,需要较久才能返回结果。这时候fping可能可以派上用场。 fping一般需要使用包管理安装。 与ping相比,fping可能是更好的工具 列出中文字体: 简短地列出中文字体: 只是删除文件的话,文件内容其实还是保存在磁盘上,可以通过特殊工具读回。shred工具则会通过随机写入数据的方式对文件内容进行覆盖。 默认使用(覆盖文件内容三次): 指定覆盖次数: 覆盖完后直接删掉文件: 可以设置一个alias: 一般使用对称算法来加密文件: 这会产生一个 指定加密算法: 指定输出文件fping:比普通ping好用
find命令
find . -type f -name "filename" -delete
,可以添加-depth 1
指定递归深度find . -regex ".*/[a-z0-9]\{32\}\.jpg" -exec mv {} ~/Desktop/ \;
,将符合条件的图片移动到桌面find ~/.hammerspoon -type f -name "*.lua" -print0 | xargs -0 wc -l
find . -type f -exec chmod 644 {} \;
find . -type d -exec chmod 744 {} \;
fc-list命令:查看字体列表
fc-list :lang=zh-cn
fc-list -f "%{family}\n" :lang=zh
shred命令:删除文件前覆盖文件内容
shred FILEPATH
shred -n 1 FILEPATH
shred -u FILEPATH
alias rm='shred -u'
gpg命令:文件加密
gpg --symmetric ${file}
${file}.gpg
的文件就是加密后的文件,但是需要注意的是,原始文件 ${file}
依然存在,不会被删除.gpg --symmetric --cipher-algo AES256 ${gpg_file}
gpg -o ${gpg_file} ${file}
gpg -o ${file} ${gpg_file}