This page looks best with JavaScript enabled

Today I Learned/Thought/Found

 ·  ☕ 11 min read
    🏷️
  • #TIL

记录每天所学到的、想到的和遇到的:

Linux coreutils 里的 rmdir 命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
man rmdir
NAME
       rmdir - remove empty directories

SYNOPSIS
       rmdir [OPTION]... DIRECTORY...

DESCRIPTION
       Remove the DIRECTORY(ies), if they are empty.

       --ignore-fail-on-non-empty
              ignore each failure that is solely because a directory is non-empty

       -p, --parents
              remove DIRECTORY and its ancestors; e.g., 'rmdir -p a/b/c' is similar to 'rmdir a/b/c a/b a'

其实也可以用 find:

1
find . -type d -empty -delete

How to remove all empty directories in a subtree?

Jetbrians IdeaVIM 的 Forward 和 Back 不工作了

nmap <C-i>    :action Forward<CR>
nmap <C-o>    :action Back<CR>

https://youtrack.jetbrains.com/issue/VIM-2225

google chrome 无法播放视频

今天发现 YouTube 无法播放视频了,于是很纳闷?难道我这几天新安装了什么插件吗?仔细一回想,没有啊。
然后我从命令行启动 Chrome 发现以下日志:

1
2
3
4
5
6
❯ google-chrome-stable
[62820:62820:0513/165342.261311:ERROR:vaapi_wrapper.cc(1136)] vaQuerySurfaceAttributes failed, VA error: invalid parameter
[62820:62820:0513/165342.261383:ERROR:vaapi_wrapper.cc(1083)] FillProfileInfo_Locked failed for va_profile VAProfileH264Main and entrypoint VAEntrypointVLD
[62820:62820:0513/165342.261421:ERROR:vaapi_wrapper.cc(1136)] vaQuerySurfaceAttributes failed, VA error: invalid parameter
[62820:62820:0513/165342.261452:ERROR:vaapi_wrapper.cc(1083)] FillProfileInfo_Locked failed for va_profile VAProfileH264High and entrypoint VAEntrypointVLD

奇怪,看起来是音视频硬件加速出了问题。

从 vainfo 发现了诡异的地方:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
❯ vainfo
vainfo: VA-API version: 1.14 (libva 2.14.0)
vainfo: Driver version: Splitted-Desktop Systems VDPAU backend for VA-API - 0.7.4
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileMPEG4Simple            : VAEntrypointVLD
      VAProfileMPEG4AdvancedSimple    : VAEntrypointVLD
      <unknown profile>               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointVLD
      VAProfileVC1Simple              : VAEntrypointVLD
      VAProfileVC1Main                : VAEntrypointVLD
      VAProfileVC1Advanced            : VAEntrypointVLD


有一行是 unknown profile

https://forum.manjaro.org/t/nvaapi-video-acceleration-on-google-chrome-stable-not-working/100109/3

从这个 issue 看到说需要安装 libva-vdpau-driver-chromium ?奇怪,以前我从来没安装过这个包啊。

1
2
  yay -S libva-vdpau-driver-chromium
  # note: Installing libva-vdpau-driver-chromium will remove: libva-vdpau-driver

安装 =libva-vdpau-driver-chromium= 完之后:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
	❯ vainfo
  vainfo: VA-API version: 1.14 (libva 2.14.0)
  vainfo: Driver version: Splitted-Desktop Systems VDPAU backend for VA-API - 0.7.4
  vainfo: Supported profile and entrypoints
		VAProfileMPEG2Simple            : VAEntrypointVLD
		VAProfileMPEG2Main              : VAEntrypointVLD
		VAProfileMPEG4Simple            : VAEntrypointVLD
		VAProfileMPEG4AdvancedSimple    : VAEntrypointVLD
		VAProfileH264Main               : VAEntrypointVLD
		VAProfileH264High               : VAEntrypointVLD
		VAProfileVC1Simple              : VAEntrypointVLD
		VAProfileVC1Main                : VAEntrypointVLD
		VAProfileVC1Advanced            : VAEntrypointVLD

再次启动 chrome 又发现新的问题

[48720:48720:0513/172226.125496:ERROR:gl_utils.cc(319)] [.WebGL-0x3b600379bf00]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels

奇怪?这次看起来是显卡的问题, GPU stall 了。

linux 的 faillock

今天感觉键盘上有很多灰尘,想擦一擦,于是先锁屏,然后用湿巾疯狂擦了几下键盘,擦完发现因不小心触碰了很多次解锁键,失败次数过多,得等 10 分钟后才能解锁。
于是了解到了: faillock

https://linux.die.net/man/8/faillock

只能以 root 身份从 tty 登录,然后

1
2
  faillock --user ${USER} --reset

vim 中的 ysiw, 和 cs

1
2
3
4
5
6
7
8

ci" - change inside double quotes

ci) - change inside curved brackets

ci} - change inside curly brackets


ysiw] surround a text object with ‘=’

https://github.com/tpope/vim-surround/issues/128

linux 下从进程的 pid 去寻找这个 pid 属于哪个 docker 容器。

今天有同事发现公司一台服务器占用的资源较多,他从 =top= 拿到了 =pid= 。
于是搜了一下, =/proc/= 下面可以查看 =/proc/${pid}/cgroup= 来得到 =containerId=

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

  ❯ docker run -d --rm --net="host" --name mymongo -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=123456 mongo:5.0.0
  e7cd5c86843ddb2fe6e1b96e24702f193bf319ffc5f667f1728bff1f7fb18d6e
  ❯ ps aux | grep -i mongod
  999      1015717 21.3  0.1 1534516 105496 ?      Ssl  16:11   0:00 mongod --auth --bind_ip_all
  exec     1016018  0.0  0.0   9760  2436 pts/74   S+   16:11   0:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn --exclude-dir=.idea --exclude-dir=.tox -i mongod
  ❯ cat /proc/$(pidof mongod)/cgroup
  0::/system.slice/docker-e7cd5c86843ddb2fe6e1b96e24702f193bf319ffc5f667f1728bff1f7fb18d6e.scope
  ❯ docker ps
  CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS         PORTS     NAMES
  e7cd5c86843d   mongo:5.0.0   "docker-entrypoint.s…"   2 minutes ago   Up 2 minutes             mymongo

今天学到了 xargs 的 –max-procs 参数。

我负责公司以太坊节点的数据导出到 apache parquet的工作,我为erigon写的导出工具是单线程的,导出数据不仅会有磁盘的I/O操作,也会有一些消耗CPU的压缩操作。
以太坊节点所在的机器有16个核,我以前是这样写并发导出脚本的:(为了突出重点,我做了精简)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
MAX_PROCESS=14
parallelCount=0
for endBlock in $(seq 10000 -1000 1); do
  ${EXPORT_CLI} &>> export.log &
  if [ ${parallelCount} -eq ${MAX_PROCESS} ]; then
    wait
    parallelCount=0
  fi
done
wait

这段代码的缺点是:在 ${parallelCount} -eq ${MAX_PROCESS} 为true的时候,程序会一直等待,即使并发任务数量降为1。这不是我能够容忍的。
于是我了解到了 xargs 的 --max-procs

-P max-procs, –max-procs=max-procs
Run up to max-procs processes at a time; the default is 1. If max-procs is 0, xargs will run as many processes as possible at a time. Use the -n option or the -L option with -P; otherwise chances are that only one exec will be done. While xargs is running, you can send its process a SIGUSR1 signal to increase the number of commands to run simultaneously, or a SIGUSR2 to decrease the number. You cannot increase it above an implementation-defined limit (which is shown with –show-limits). You cannot decrease it below 1. xargs never terminates its commands; when asked to decrease, it merely waits for more than one existing command to terminate before starting another.

于是我将代码这样修改:

1
2
3
4
5
6
7
function run_export_trace(){
  block=$1
  export_cli=$2
  ${export_cli} &>> export.log
}
export -f run_export_trace
seq 14340000 -${STEP} 1 | xargs -i --max-procs ${MAX_PROCESS} bash -c  "run_export_trace {} ${EXPORT_CLI}"

完美!这样cpu就不会闲着了。

我想将我的私人文件不被 git track, 但又不方便加入到 .gitignore 里面

我在和他人合作开发一个项目的时候,会自己写很多私有的脚本,每次在 git add 的时候都要关心一下有没有把不该track的东西给track了,本来可以加入到 .gitignore 里, 但是我又不想把我的私人文件加入到 .gitignore 里。
搜了一下, 也可以加入到 .git/info/exclude 里, 这个文件不会被 git track.
https://git-scm.com/docs/gitignore

Linux umount 时遇到: target is busy

今天坐在我工位对面的同事尝试对存放以太坊节点数据的磁盘执行 umount操作, 遇到了 target is busy这个问题。我的直觉告诉我这应该是有个进程正在读写这块硬盘。所以 umount 才会失败。
于是立即学习一下 core/psmisc 包里面的fuser 命令,和 lsof 命令。

从man手册可以查到:

fuser: fuser displays the PIDs of processes using the specified files or file systems.

fuser returns a non-zero return code if none of the specified files is accessed or in case of a fatal error. If at least one access has been found, fuser returns zero.

fuser 的ACCESS 列展示了相关进程的具体 access 信息

 c      current directory.
 e      executable being run.
 f      open file.  f is omitted in default display mode.
 F      open file for writing.  F is omitted in default display mode.
 r      root directory.
 m      mmap'ed file or shared library.
 .      Placeholder, omitted in default display mode.

fuser 有 -m 选项:

-m NAME, –mount NAME
NAME specifies a file on a mounted file system or a block device that is mounted. All processes accessing files on that file system are listed. If a directory is specified, it is automatically changed to NAME/ to use any file system that might be mounted on that direc‐
tory.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
❯ fuser -m /run/media/exec/vax/ -v
                     USER        PID ACCESS COMMAND
/run/media/exec/vax: root     kernel mount /run/media/exec/vax
                     exec      269858 ..c.. zsh
                     exec      269933 f...m gitstatusd-linu
❯ fuser -m /run/media/exec/vax/ -v
                     USER        PID ACCESS COMMAND
/run/media/exec/vax: root     kernel mount /run/media/exec/vax
                     exec      269933 f...m gitstatusd-linu
❯ fuser -m /run/media/exec/vax/ -v
                     USER        PID ACCESS COMMAND
/run/media/exec/vax: root     kernel mount /run/media/exec/vax
                     exec      269933 f...m gitstatusd-linu
❯ fuser -m /run/media/exec/vax/ -v
                     USER        PID ACCESS COMMAND
/run/media/exec/vax: root     kernel mount /run/media/exec/vax

我注意到,即使我的zsh 离开了 外置硬盘所在的目录时, 这个硬盘依然被使用着,因为我用了 zsh 的一个 git status daemon 插件,这个插件估计会定时获取远程 git 仓库的状态。所以 fuser 展示了 gitstatusd-linux
后来我退出了 zsh shell, gitstatusd-linux 才退出。

https://unix.stackexchange.com/questions/3109/how-do-i-find-out-which-processes-are-preventing-unmounting-of-a-device

vim 使用 column 命令将若干列文本对齐

我的需求是这样的,想把这三列文本从上面的样子变成下面的样子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    private String transactionHash;
    private String blockHash;
    private Long blockNumber;
    private String fromAddress;
    private Long gas;
    private Long gasPrice;
    private String input;
    private Long nonce;
    private String toAddress;
    private Integer transactionIndex;
    private BigDecimal transactionValue;
    private Long blockTimestamp;
    private Receipt receipt;


private  String      transactionHash;
private  String      blockHash;
private  Long        blockNumber;
private  String      fromAddress;
private  Long        gas;
private  Long        gasPrice;
private  String      input;
private  Long        nonce;
private  String      toAddress;
private  Integer     transactionIndex;
private  BigDecimal  transactionValue;
private  Long        blockTimestamp;
private  Receipt     receipt;

只需进入 vim 的VISUAL 模式,选中那十几行,然后 :!column -t 即可。

将 Google NCR 设置为浏览器默认搜索引擎

我不喜欢 google 返回我和我位置信息相关的搜索结果,于是设置一下 Google NCR (No Current Region)
https://10wontips.blogspot.com/2018/07/always-search-google-in-english-by.html

我今天学到的 Linux 命令: disown

为了搞懂 disown 命令,必须得搞明白 linux 的 jobs 这个概念。
job 其实就是 shell 管理下的进程,每个 job 都有唯一的 job ID , job 有 3 中状态: foreground , background (在命令末尾用了 & 符号), stopped (按下 Ctrl-Z 会使得前台进程处于该状态)
与 job 相关的命令有这几个:

1
2
3
jobs # 列出 jobs 列表
bg %n # 让该 job 在后台工作
fg %n # 让该 job 在前台工作

如果你其他以 cmd & 的方式让一个进程工作在后台,当你退出 shell 后,该进程就会挂掉,要么你用 nohup 来启动,或者考虑 disown

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ help disown
disown: disown [-h] [-ar] [jobspec ... | pid ...]
    Remove jobs from current shell.

    Removes each JOBSPEC argument from the table of active jobs.  Without
    any JOBSPECs, the shell uses its notion of the current job.

    Options:
      -a        remove all jobs if JOBSPEC is not supplied
      -h        mark each JOBSPEC so that SIGHUP is not sent to the job if the
                shell receives a SIGHUP
      -r        remove only running jobs

    Exit Status:
    Returns success unless an invalid option or JOBSPEC is given.

disown 可以让指定 job 从job table 中移除,这样 即使你退出 shell, 后台进程也不会挂掉。
其中 -h 参数可以让 disown 在终端退出之后才生效。

vim 用户必须了解的 的 motion 和 operation

https://www.barbarianmeetscoding.com/boost-your-coding-fu-with-vscode-and-vim/editing-like-magic-with-vim-operators/

awk 不定长句子的最后一个单词:

1
awk '{ print $(NF) }'

NF 表示这行句子的字段数。

vmtouch: 一个可以分析/控制文件系统缓存的工具

我拥有很多 roamXXXX.org 文件, 还有一个超级大的 org-journal文件,每当我第一次用emacs打开这些大文件后,感受到明显的卡顿,我认为这明显的卡顿其中从磁盘冷加载文件贡献了 30% 的卡顿,然后就是解析大文件,格式化和 highlight 贡献了 70% 的卡顿。于是我想让电脑在第一次开机的时候,将这些预读一下,旁加载到page cache里。最简单粗暴的方法,就是写个循环,把这些文件都 cat * > /dev/null, 后来找到了更为优雅的工具: vmtouch
https://hoytech.com/vmtouch/

1
2
3
vmtouch -vt ~/.emacs.d/
vmtouch -vt ~/org/roam/
vmtouch -vt ~/org/daily/

vmtouch 可以将文件 touch 进内存, 也可以将内存中的文件缓存 evict 出内存。

vmtouch 的用了这些系统调用:

1
2
3
4
5
6
#include <sys/mman.h>
int mincore(void *addr, size_t length, unsigned char *vec);

#include <fcntl.h>
int posix_fadvise(int fd, off_t offset, off_t len, int advice);

scrcpy 控制安卓手机

我拥有一个安卓手机,没有 root,今天想通过 Linux 系统来控制手机,于是折腾了一下,找到了 scrcpy 这个包:

1
2
3
❯ sudo pacman -Ss scrcpy
archlinuxcn/scrcpy 1.19-1 [installed]
    Display and control your Android device

https://github.com/Genymobile/scrcpy

注意是scrcpy不是scrapy, scrapy是 python 的一个爬虫框架,我们需要的是scrcpy
我本来可以通过 usb 数据线链接手机,然后开启 adb 调试模式的,但是嫌麻烦。找到了通过 wifi 链接手机 adb 调试的方案:
并且通过 adb 解锁手机锁屏。
https://stackoverflow.com/questions/29072501/how-to-unlock-android-phone-through-adb
这样就能愉快的操控手机了~

Linux 控制外接显示器的亮度

因为我最近把外接显示器放置的比较远,我目前在坐的位置是面对窗户并且面朝东。早上阳光非常刺眼,就得将显示器亮度调高点才合适,晚上又得吧显示器亮度调暗。我懒得伸手去操作显示器,所以从终端控制:
我用的 archlinux,需要这个包

1
2
3
4
❯ sudo pacman -Sii ddcutil
Repository      : extra
Name            : ddcutil
Description     : Query and change Linux monitor settings using DDC/CI and USB.

然后 load i2c-dev module

1
modprobe i2c-dev

现在 ddcutil 就可以使用了:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  ~
❯ sudo ddcutil capabilities | grep "Feature: 10"
   Feature: 10 (Brightness)
  ~
❯ sudo ddcutil getvcp 10
VCP code 0x10 (Brightness                    ): current value =    50, max value =   100
  ~
❯ sudo ddcutil setvcp 100
Missing argument(s)
  ~
❯ sudo ddcutil setvcp 10100
  ~
❯ sudo ddcutil capabilities | grep "Feature: 10"
   Feature: 10 (Brightness)
  ~
❯ sudo ddcutil getvcp 10
VCP code 0x10 (Brightness                    ): current value =    50, max value =   100
  ~
❯ sudo ddcutil setvcp 10 100
  ~
❯ sudo ddcutil setvcp 10 20
  ~
❯ sudo ddcutil setvcp 10 100

大功告成,以后我再也不用伸胳膊去够显示器后面的调节按钮了。
:-D

Wikiwand: Wikipedia Modernized, 一个可以让你的 wikipedia 页面更好看的 chrome 插件!

https://chrome.google.com/webstore/detail/wikiwand-wikipedia-modern/emffkefkbkpkgpdeeooapgaicgmcbolj

使用 kdeconnect-cli 为手机分享文件或文字

因为懒得去动鼠标/触摸板来 操作 kdeconnect 的图形界面,所以研究了一下如何在终端里将文件分享给手机。

1
2
3
4
5
kdeconnect-cli -l
kdeconnect-cli -a --id-only
kdeconnect-cli -d ${deviceid} --ping
kdeconnect-cli -d ${deviceid} --share ${realpath_of_file}
kdeconnect-cli -d ${deviceid} --share-text ${text} # 这会把文本分享给手机的粘贴板。

https://userbase.kde.org/KDE_Connect/Tutorials/Useful_commands

一个可以为远古时期的网页设置 syntax highlighting 的 firefox 插件:Enlight

https://addons.mozilla.org/en-US/firefox/addon/enlight/

zsh 快捷键相关的

其实很久以前就知道 bash/zsh 有很多移动鼠标的快捷键是从 emacs 那里移过来的。
今天我在 zsh 下工作时,巧合地触发了 M-x 键,它给我弹出了个 execute prompt, 于是我研究一番,zsh 下的 M-x 竟然和 emacs 的 M-x 相通,都是用来execute-command的
https://unix.stackexchange.com/questions/440159/regarding-altx-in-zsh-and-how-to-bind-altx-to-something-else

ssh forward 遇到 bind: Cannot assign requested address

我今天在执行ssh -N -L port1:address:port2 server 时遇到了这个问题:
https://www.electricmonk.nl/log/2014/09/24/ssh-port-forwarding-bind-cannot-assign-requested-address/
原来是 ssh 试图 bind ipv6 地址
指定 ssh -4 使用 ipv4 地址 即可。

用命令行将 html 导出为图片

  1. 用 google-chrome
1
google-chrome-stable --headless --disable-gpu --virtual-time-budget=10000 --window-size=3840,2160 --screenshot https://www.google.com

List of Chromium Command Line Switches

https://developers.google.com/web/updates/2017/04/headless-chrome
https://dschnurr.medium.com/using-headless-chrome-as-an-automated-screenshot-tool-4b07dffba79a

  1. 用 wkhtmltoimage
1
wkhtmltoimage --width 1980 --height 1024  --quality 100 --javascript-delay 10000 https://www.google.com google.png

Emacs 将 org-journal-entry 同步到 telegram channel 里

我使用 org-journal 来记录生活,但是 org-journal 是离线的,我创建了个 bot 来将单条 org-journal-entry 同步到 channel里。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
(defun exec/get-org-entry-summary ()
  (interactive)
  (setq urlraw (format
    "https://api.telegram.org/bot%s/[email protected]%s&text="
    (read-file "/home/vory/.emacs.d/config/tgsync.token")
    (read-file "/home/vory/.emacs.d/config/chatid.priv")
    ))
  (setq urlraw (concat urlraw   (buffer-substring (line-beginning-position) (line-end-position))))

  (message urlraw)
  (setq urlq (url-encode-url urlraw))

  (setq url-proxy-services
  '(("http" . "127.0.0.1:1081")
	("https" . "127.0.0.1:1081")))
  (url-retrieve-synchronously urlq)
  (message "sync to telegram channel success"))

茴香豆的茴有几种写法之 VIM 有哪几种退出方式?

  • :wq / ZZ / :x
  • :q! / ZQ

日志里面第一列是 ip, 查询出现次数前 10 的 ip

1
cat xxx.log | awk '{ print $1 }' | sort -n | uniq -c | sort -r -k1 | head 10

grep pdf 文件

ripgrep-all

为 tmux 的 pane 名称设置不同的 emoji 后缀

生活要过的多姿多彩,同样的,我的终端也必须多姿多彩。于是我给 tmux的panel添加了随机的emoji后缀
写一个shell脚本,放进我喜欢的emoji

1
2
3
4
EMOJIS=(😀 😃 😄 😁 😆 😅 🤣 😂 🙂 🙃 😉 😊 😇 🥰 😍 🤩 😘 )
SELECTED_EMOJI=${EMOJIS[$RANDOM % ${#EMOJIS[@]}]};
echo -n $SELECTED_EMOJI

然后在tmux里这样设置pane的名称,:

1
set-option -g automatic-rename-format '#{b:pane_current_path}[#(/home/vory/Dotfiles/tmux/pick.sh)]'

大功告成!

direvent:

GNU direvent - Summary [Puszcza]

OCR 应用: tesseract

有时候身边的同事在排查问题的时候,会从用户那里得到图片形式的hash,为了debug,我本可以手工将图片形式的哈希转化为文本形式的,可是我实在是嫌麻烦,于是玩了下这个从 2006 年开始由Google maintain 的 OCR工具: tesseract-ocr/tesseract

ArchLinux 下所需的包

tesseract

1
> sudo pacman -S tesseract tesseract-data-chi_sim tesseract-data-chi_tra tesseract-data-eng

第一个是主程序,其他的都是由Google训练好的中文和英文模型库。
tesseract 的使用规则是这样的:

1
2
3
4
 tesseract FILE OUTPUTBASE [OPTIONS]... [CONFIGFILE]...
 # If FILE is stdin or - then the standard input is used.
 # If OUTPUTBASE is stdout or - then the standard output is used.

我的使用流程是: 从屏幕上截图,截图会自动保存到粘贴版,然后:

1
xclip -sel clip -target image/png -o | tesseract stdin stdout -l chi_sim -c preserve_interword_spaces=1

如果不加preserve_interword_spaces=1 的话,识别出的结果就会有烦人的空格。

结果很准确,甚至是同时有中文英文和符号的图片都能识别!

使用 sed 获取一个文件位于两个关键词之间的内容

比如:

> cat file.txt
first line :head
second line
third line
apple
forth line
...
tiger
last line
tail
1
2
3
4
5
6
> sed -n '/apple/,/tigger/p'  file.txt
apple
forth line
...
tiger

goland 缺失的功能

我用goland开发公司的项目,很喜欢goland的rename usages of 变量/函数 A to 变量/函数 B的功能,但是我却不能对 import 这么做, 要是想改变整个项目都某一个包的引用,不得不使用 sed:

1
find . -name '*.go' -type f -exec sed -i 's/tg-service/tg-service\/bridge/g' {} ';'

*nix 环境,快速生成大量随机的 leetcode 测试用例

当我在 leetcode做了一道算法题后, 我会先在心里考虑一下输入的边界情况(或者非法输入),时间复杂度(要是数据里过大并且我的算法时间复杂度太差就会 Time Limit Exceed)。

所以我要么手动在 test cases 里手写测试用例, 要么用 linux 下这么几个有用的命令随机生成大量的测试用例:

1
2
3
4
5
6
seq  # print a sequence of numbers

shuf #  generate random permutations

paste #   merge lines of files

用这三个简单的工具, 一般就能生成我想要的测试数据了。
比如我想生成一个数组, 数组的每个元素都是数字,整个数组要是 unsorted:

1

要是想要超大的数据量, 我一般会写到 /tmp/ 里,再配合 xclip 将内容读进到 粘贴板, 最终粘贴到网页里去

https://leetcode.com/problems/combination-sum/solution/

1
2
3

seq 100 | shuf | paste -s -d ,

我喜欢用 printf 配合这些工具输出我想要的格式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
> cat gen.sh
N=100
if [[ $# -eq 1 ]];then
    N=$1
fi
for n in $(seq $N) ;
do
    if [[ $(($RANDOM % 3 )) -eq 0 ]];then
        echo $n
    fi
done


> printf "[%s]\n" "$(./gen.sh 365 | paste -s -d , )"

[3,10,11,18,21,22,32,37,40,44,45,46,48,50,52,53,55,57,61,63,64,65,66,68,69,76,79,90,91,93,95,96,99,100]

> printf "[%s]\n" "$(./gen.sh 365 | paste -s -d , )" | xclip -sel clip
# 生成随机结果, 并且复制到粘贴板

心中的疑惑

  1. 在终端里快速生成大量随机数的最佳实践是什么?

gorm 链接 MySQL 处理 Error 1390 错误

我在公司负责的项目中使用了 gorm, 有一次 批量插入数据时遇到了 1390 :too many placeholders
所以我不得不减少数据量,为了解决问题将代码这样修改:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import(
    gmysql "github.com/go-sql-driver/mysql"
)
type Transactions []Transaction

func (ts Transactions) Insert() error {
	if len(ts) == 0 {
		return nil
	}

	err := db.Clauses(clause.OnConflict{
		DoNothing: true,
	}).Create(&ts).Error
	if err == nil {
		return nil
	}

	var mysqlErr *gmysql.MySQLError
	if errors.As(err, &mysqlErr) && mysqlErr.Number == 1390 {
		mid := len(ts) / 2
		if err := ts[:mid].Insert(); err != nil {
			return err
		}
		if err := ts[mid:].Insert(); err != nil {
			return err
		}
		return nil
	}
	return err
}

https://stackoverflow.com/questions/18100782/import-of-50k-records-in-mysql-gives-general-error-1390-prepared-statement-con

Share on

EXEC
WRITTEN BY
EXEC
Evil EXEC