#11 Shell 循环执行

2023-03-23

根据《今天我靠chatgpt早下班2小时!太强了!》整理:

#!/bin/bash

# 锁文件路径
lockfile="/tmp/my.lock"

function cleanup {
    echo "清理锁文件"
    rm -f "$lockfile"
    exit 1
}
# 注册清理函数,确保无论脚本如何退出都会执行
trap cleanup EXIT

if [ -e "$lockfile" ]; then
    echo "WARNING: 另一个实例正在运行!"
else
    touch "$lockfile"
    echo "脚本开始执行"
    while true; do
        sh a.sh
        sleep 300  # 5分钟的间隔时间,单位为秒
    done
    rm "$lockfile"
    echo "脚本退出执行"
fi

#9 zsh: you have running jobs.

2021-09-09

我定义了一个 gitg 的快捷方式:

function _new_gitg () {
    # alias g='gitg --all >/dev/null 2>&1 &'  # 覆盖 g=git
    if [ -z "$1" ]; then
        nohup gitg --all >/dev/null 2>&1 &!
    else
        nohup gitg -s $1 >/dev/null 2>&1 &!
    fi
}
alias g='_new_gitg'

但是每次退出 shell 会有提示:zsh: you have running jobs.

我就加上 nohup,以为不会有提示,但提示依旧(不过强制退出也不会关闭 gitg 就是了)。

在 SO 上搜到相同问题,这个答复就可以很好的解决我的问题:

If you want to not see that message, simply pass the job id to disown, like so:

> disown %1
> ```
>
> Or, start the job with &! (zsh-specific trick):
>
> ```sh
> nohup ./my_script.sh &!
> ```

```sh
function _new_gitg () {
    if [ -z "$1" ]; then
        nohup gitg --all >/dev/null 2>&1 &!
    else
        nohup gitg -s $1 >/dev/null 2>&1 &!
    fi
}
alias g='_new_gitg'

经过测试,这个技巧在 bash 5.1.4 下也有效。

#8 使用 nohup 的一个小问题

2021-07-22
function fq () {
    # ...
    nohup qv2ray &>> /tmp/qv2ray.log &
    # ...
}

每次关闭终端,qv2 就一起崩溃了。

然后我改成:

nohup sh -c "qv2ray &>> /tmp/qv2ray.log &"

就好了。

分析:可能是后面日志和改后台运行的部分被 nohup 拿走的缘故吧。

#7 高效搜索日志

2020-07-22

即便上了 ELK,也不可能所有日志往里面塞,搜日志是程序员的日常工作之一。

grep log by time efficiently 为关键词搜到 SO 上的这个问题: What is the most efficient way to extract logs between two time stamps?

要求:

  1. 能够过滤出指定时间段日志
  2. 效率,保证即便是大日志也不至于等太久,减少对服务的不良影响

提问的人自己提出来的方案:

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

#6 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))

#5 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'

#4 Shell 历史

2020-01-07

参考: https://en.wikipedia.org/wiki/Comparison_of_command_shells

Linux Shell

  • Thompson shell (sh), 1971, Unix v1 - v6
    只存在历史中
    在 Bourne shell 之前,贝尔实验室还出了一个 Mashey shell,只出现在 1976 年的 PWB UNIX 中(所以又叫 PWB shell),没有大范围使用
  • Bourne shell (sh), 1977, Unix v7
  • C shell (csh), 1978 img
  • TENEX C shell (tcsh), 1983 img
    是 TENEX 系统开发的 csh 兼容 Shell
  • Korn shell (ksh), 1983 img
  • Bash, 1989 img
  • Almquist shell (ash), 1989 img
  • zsh, 1990 img
  • Debian Almquist shell (dash), an ash fork, 1997
    主体随 ash 是 BSD 协议,不过,可能是为了保持对 bash 的兼容,采用了 bash 项目的一个文件
  • fish, 2005 img

分类

  • ksh, bash, zsh, ash, dash 都是 Bourne shell 兼容。
  • csh, tcsh 就是 csh 兼容。
  • fish

说明

  1. Unix 上的 sh 有版权问题, 所以 BSD 和 Linux 上的 /bin/sh 都指向某一种兼容 Shell (一般是默认 Shell)
  2. RHEL/CentOS 上,默认 Shell 是 Bash
  3. Debian/Ubuntu 上,默认 Shell 是 Dash
  4. FreeBSD 上默认采用 tcsh, 基于 FreeBSD 的 GhostBSD 采用 fish
  5. OpenBSD 上默认采用 pdksh (pd: Public Domain), 不知道和 tsh 什么关系。可能是 OpenBSD 维护的 tsh 兼容 Shell。
  6. NetBSD 上默认采用 ash
  7. 由于 ash 非常轻量级,BusyBox 采用了 dash fork
    然后 BusyBox 被 Alpine Linux, Tiny Core Linux 或者其他嵌入式 Linux (比如 OpenWrt) 采用,所以这些系统的默认 Shell 应该就是 ash

所以可能使用最广泛的 Shell 是 ash 和 bash。

其他:MacOS 上曾经默认采用 bash, 后来专向了 zsh

Windows 平台

  • command.com, 1980
  • cmd.exe, 1993
  • PowerShell, 2006

#3 Shell 编程备忘录

2019-08-21

PS: Shell 编程时总是不能区分什么是 Shell 语法,什么是系统命令。

基础

x=abc

echo hello world
echo 'Just output $x'
echo "The value of x: $x"

echo ${x:?变量未设置}
echo ${x:+变量已设置}
echo ${x:-默认值}

变量

Shell 就是标准的弱类型,所有的数据都是按照字符串的形式存储,然后根据上下文决定如何处理。

x='hello world' # 等于号两边不能有空格
local x='hello world' # 本地作用域,函数体中使用
echo $a
echo ${a}

unset a
readonly a  # 将变量设置成只读,不能修改,不能 unset
readonly b=1
# 没有提供方法取消 readonly 属性,但是我看到 SO 上有提供非常规方法来做这件事情

字符串变量

单引号不支持变量和转义(也就是说字符串中不能出现单引号)!

x="hello world"
echo $x

echo ${#x}
echo ${x/world/markjour} # 字符串替换

# 子字符串/字符串切片
echo ${x::5}  # hello
echo ${x:7:8} # world
echo ${x::4}  # hell
echo ${x::-4} # hello w

特殊变量

$0
$1
...
$n

# 所有参数
$*
$@

$# # 参数个数
$$ # 进程号
$! # 后台进程号
$? # 上一个命令的退出状态
$- # himBHs 当前 Shell 的选项

数组

arr=(zhao qian sun li)
arr[4]=zhou
arr[5]=wu
arr[6]=zheng
arr[7]=wang
echo ${arr[0]} # zhao
echo ${arr[@]} # zhao qian sun li zhao wu zheng wang

# 获取数组元素个数
echo ${#arr}    # 4 定义时的长度,后来新加的不算,也就是说这个值定义变量的时候就定了
echo ${#arr[@]} # 8

条件

if condition:
then
    :
else:
    :
fi
  • [ ]
  • [[ ]]
  • test

循环

for var in list:
do
    :
done

数学计算

test

逻辑

数学比较

字符串比较

文件相关

bcdfgkpurwxse
白菜豆腐干,靠谱如我,羞涩

最常用的:

  • -e 检查路径是否存在
  • -d 检查是否为目录
  • -f 检查是否为文件
  • -r 检查文件是否可读
  • -w 检查文件是否可写
  • -x 检查文件是否可执行
  • -s 检查文件是否为空

参考资料与拓展阅读

#2 Web 保存数据的特殊方案

2018-11-08

将数据通过编码存在图片里面,实现导出导入功能。
虽然我不知道什么场景下需要使用这个方案,但这个想法特有意思。