Linux scp
2021-07-15
背景:有一个服务会定时读某个目录下的文件,然后逐个进行处理。
今天出于某些原因,我通过 scp 拷贝文件到那个目录下,结果意外的发现服务挂掉了,就是因为读到了一个空文件,抛出一个没有被处理的错误。
我知道这是程序设计上存在的一个缺陷,但之前我们一直通过 rsync 在传输文件,从来没有遇到过这样的问题。
我查了文档并进行了实验,确认了 rsync 会在文件传输时创建一个 .文件名.随机串 的临时文件,然后在传输完成后重命名。而 scp 则不会这样做,它会创建空文件,然后逐渐填充内容。
If the target file does not yet exist, an empty file with the target file name is created, then filled with the source file contents. No attempt is made at "near-atomic" transfer using temporary files.
我的理解是,文档里面说的 near-atomic 应该就是指 rsync 那种模式,而 atomic 的意思应该是指连临时文件都不用创建的模式。也不知道有什么文件系统支持这种模式。
服务器 操作系统 Linux CentOS Debian Ubuntu
2021-07-15
列一下常见的服务器操作系统。
计算机网络 Linux
2021-03-15
早几年前,Linux 系统的网卡名称都是 eth0、wlan0,后来都变了个风格,就拿我的电脑举例:enp7s0, wlp6s0。
这到底是是什么原因呢?
最近突然好奇,去查了资料才知道为什么。
在 Fedora 的技术资料中找到,这个和 Systemd 有关,然后又在 freedesktop 官网 Systemd 的手册中找到了详细的说明。
现在的命名方案有好长一段,估计要看个半个小时(如果感兴趣可以仔细阅读一下),解开我的疑问却不需要那么复杂。
Linux DEB
2021-03-13
输出 dot 格式的包依赖关系图,可以用 graphviz 生成图片。
Linux 开发工具 jq JSON
2021-03-04

jq 是我在命令行中解析 JSON 的一个常用工具,用起来非常顺手。
- https://github.com/stedolan/jq
- https://stedolan.github.io/jq/
用法
curl https://24pullrequests.com/users.json | jq
# 取第一个元素
curl https://24pullrequests.com/users.json | jq '.[0]'
# 取第一个元素的指定字段
curl https://24pullrequests.com/users.json | jq '.[0].nickname'
# 切片
curl https://24pullrequests.com/users.json | jq '.[:2]'
# 遍历
curl https://24pullrequests.com/users.json | jq '.[] | .nickname'
# 取字段
curl https://24pullrequests.com/users/changeworld.json | jq .nickname
# 取多个字段
curl https://24pullrequests.com/users/changeworld.json | jq '.nickname,.contributions_count'
# 获取列表长度
curl https://24pullrequests.com/users.json | jq length
# 列出 Keys
curl https://24pullrequests.com/users/changeworld.json | jq keys
curl https://24pullrequests.com/users/changeworld.json | jq "keys[]"
curl https://24pullrequests.com/users.json | jq ".[0] | keys[]"
# 列出 Keys 和 值类型
cat a.json | jq ".[0] | keys,map(type)"
cat a.json | jq ".[0] | to_entries | map([.key, (.value | type)])"
cat a.json | jq '.[0] | to_entries | map("\(.key) : \(.value|type)")[]'
还有很多更强大的用法,可以参考文档,我就会上面几个,在命令行中简单搜索 JSON 也够用了。
刚在文档中学会一招,重新组合 JSON:
curl https://24pullrequests.com/users/changeworld.json | jq '[.nickname, .organisations[].login]'
curl https://24pullrequests.com/users/changeworld.json | jq '{name:.nickname, orgs:[.organisations[].login]}'
👍🏻 Nice!!!
Linux CentOS
2020-12-10
刚才在 linux.cn 上看到这篇文章:CentOS 8 落幕,“免费” 的 RHEL 没了。
大意就是说 CentOS 项目组集中全力开发 CentOS Stream 作为 RHEL 上游。作为 RHEL 再发布版本的 CentOS 不会继续发布了。
邮件列表原文链接:https://lists.centos.org/pipermail/centos-announce/2020-December/048208.html
Linux Shell
2020-07-22
即便上了 ELK,也不可能所有日志往里面塞,搜日志是程序员的日常工作之一。
以 grep log by time efficiently 为关键词搜到 SO 上的这个问题: What is the most efficient way to extract logs between two time stamps?
要求:
- 能够过滤出指定时间段日志
- 效率,保证即便是大日志也不至于等太久,减少对服务的不良影响
提问的人自己提出来的方案:
grep -a -A 1000000 "03/09" fileName.txt | grep -a -B 1000000 "03/10"
他认为不好,因为有点慢,而且有时会漏掉一些日志。
漏掉日志可能和他的日志格式有关,这倒应该问题不大,主要是这个方案看起来就确实效率不行。
PS:如果不用模式匹配,可以加上 -F,应该可以提高效率。
# 2020/07/22 10:00:00,100 INFO [main] com.example.LoggingApplication - Starting Application
awk '$2>="16:30:00"{s=1} s; $2>="17:00:00"{exit}' event.log
这个看起来很牛逼,主要是有一个 exit。
Linux Shell
2020-07-21
这篇文章不是要记录那些乱七八糟的转义规则,而是讲怎么借助工具避开它。
GitHub 上偶然看到一个仓库 chrissimpkins/shellescape,做了些实验之后,发现非常好用。
别看就几行代码,真的感觉世界都清静了。
PS:代码我没细看,人生短暂,我不想去记这些没用的知识点。
import re
_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
def quote(s):
if not s:
return "''"
if _find_unsafe(s) is None:
return s
return "'" + s.replace("'", "'\"'\"'") + "'"
示例:
commands = """
grep -F '"userId": "1"' /tmp/test.log
grep 'aaa.bbb.$100.*' /tmp/test.log
""".strip().splitlines()
for command in commands:
print(quote(command))
Linux Shell
2020-07-20
快速输入上一行命令的最后一个参数
touch nihao.txt
code !$
创建目录并进入
take xxx # oh-my-zsh
mkdir xxx && cd $_
重命名
for i in {0..100}; do touch aaa_bbb_$i.jpg; done
rename 's/_bbb//' aaa_*.jpg
# for zsh
autoload zmv
zmv -n '(*)_(*).jpg' '$2_$1.jpg'
Linux 日志
2020-06-23
查看这个进程打开了哪写文件
-> % ps -ef | grep rsyslogd | grep -Fv grep
syslog 1068 1 0 1月06 ? 00:00:03 /usr/sbin/rsyslogd -n -iNONE
-> % sudo ls -l /proc/1068/fd
总计 0
lr-x------ 1 root root 64 1月 8 16:54 0 -> /dev/null
l-wx------ 1 root root 64 1月 8 16:54 1 -> /dev/null
l-wx------ 1 root root 64 1月 8 16:54 10 -> /var/log/kern.log
l-wx------ 1 root root 64 1月 8 16:54 11 -> /var/log/auth.log
l-wx------ 1 root root 64 1月 8 16:54 2 -> /dev/null
lrwx------ 1 root root 64 1月 6 09:46 3 -> 'socket:[13299]'
lr-x------ 1 root root 64 1月 8 16:54 4 -> /dev/urandom
lrwx------ 1 root root 64 1月 8 16:54 5 -> 'socket:[27825]'
lrwx------ 1 root root 64 1月 8 16:54 6 -> 'socket:[27831]'
lr-x------ 1 root root 64 1月 8 16:54 7 -> /proc/kmsg
lrwx------ 1 root root 64 1月 8 16:54 8 -> 'socket:[22468]'
l-wx------ 1 root root 64 1月 8 16:54 9 -> /var/log/syslog
查看哪些进程打开了这个文件
-> % sudo find /proc/*/fd -ls | grep /var/log/syslog
2551982 0 l-wx------ 1 root root 64 1月 8 16:50 /proc/1068/fd/9 -> /var/log/syslog
-> % ps -fq 1068
UID PID PPID C STIME TTY TIME CMD
syslog 1068 1 0 1月06 ? 00:00:03 /usr/sbin/rsyslogd -n -iNONE