简介:本资源为地震数据分析软件SAC(Seismic Analysis Code)的Linux x86_64版本安装包,主要面向地震学研究者、地球物理专业学生及需要处理地震波形数据的科研人员。SAC是地震学领域广泛使用的工具,支持SAC、MiniSEED、SEED等格式之间的相互转换,便于数据在不同分析平台与数据库间流通。压缩包共包含550个文件,以m、z、e、n、c、f等源码与头文件为主,辅以csh、sh脚本、readme说明文档及sac、makefile等配置与编译文件,整体约3.59MB,解压后可获得完整的程序源码、宏命令与帮助文档。目前已有689人学习下载。对于需要将SAC格式数据转换为MiniSEED或SEED格式、或反向读取其他系统数据的用户,该包提供了从编译安装到格式转换的完整支持,目录结构清晰,便于按模块查阅与二次开发。
1. 从 sac-101.5c-linux_x86_64.tar.gz 说起:一个地震处理二进制包在 Linux 上到底怎么落地
如果你在 Linux 服务器上拿到一个sac-101.5c-linux_x86_64.tar.gz,第一反应大概率是「解压就能用吧」。我当初也这么想,结果tar -xzf之后敲sac,终端回了一句command not found,翻车得很干脆。SAC 全称 Seismic Analysis Code,是地震波形处理领域用了三十多年的老牌工具,101.5c 是它一个相当稳定的版本分支,后面还跟着 101.6a 这类小版本迭代。这个 tar.gz 包本质上是官方预编译好的 x86_64 二进制发行版,不是源码,所以它不需要你./configure && make,但也正因为是预编译,它对系统库、环境变量、shell 类型都有隐性要求。这篇笔记面向的是手里已经攥着这个包、想在一台 Linux 机器上把它跑起来并真正处理数据的人——不管你是地震学研究生、观测台站运维,还是做嵌入式 Linux 项目时顺手要跑个波形滤波的工程师。我会把解压、环境配置、参数文件、常见报错和进阶批处理一条线讲透,让你少走我当年那两天的弯路。
2. 解压之前先看清:sac-101.5c 包结构与依赖关系
2.1 tar.gz 里到底装了什么
拿到sac-101.5c-linux_x86_64.tar.gz,别急着解压,先tar -tzf看一眼目录树。常见的官方发行包结构大致是这样:顶层一个sac-101.5c/目录,里面分bin/、lib/、inc/、aux/、doc/几个子目录。bin/下是sac主程序和saclst、sacinit等辅助工具;lib/放的是 SAC 自己的一批动态库和静态库;inc/是给二次开发用的头文件;aux/里是默认的宏和命令脚本;doc/是手册。理解这个结构很重要,因为后面配环境变量时,SACAUX要指向aux/,SACLIB要指向lib/,指错了程序能启动但一读数据就报奇怪的错。
# 先看包内结构,不解压 tar -tzf sac-101.5c-linux_x86_64.tar.gz | head -40 # 确认无误后解压到指定目录,我习惯放 /opt sudo mkdir -p /opt/sac sudo tar -xzf sac-101.5c-linux_x86_64.tar.gz -C /opt/sac --strip-components=1--strip-components=1的作用是剥掉顶层那层sac-101.5c/目录,让内容直接落在/opt/sac下。这样后面环境变量写起来干净。如果你不加这个参数,路径就会变成/opt/sac/sac-101.5c/bin,多一层,容易在脚本里写错。解压完ls /opt/sac/bin应该能看到sac可执行文件。
2.2 依赖库与系统兼容性检查
预编译二进制最怕的就是动态库缺失。解压后先别配环境变量,直接ldd查一下主程序的依赖:
ldd /opt/sac/bin/sac | grep "not found"如果输出为空,说明系统库齐全,可以直接用。如果列出libX11.so.6、libXm.so.4之类not found,说明缺图形界面相关的库。SAC 的plot系列命令依赖 X11 和 Motif,纯命令行处理波形其实用不到,但程序启动时会去加载,缺了就直接起不来。CentOS 7 上一般yum install libX11 libXm能补上;Debian 系则是apt install libx11-6 libxm4。这里有个血泪经验:不要为了省事去装libXm的开发包,运行期只要运行库,装开发包反而可能引入版本冲突。
提示:如果你的机器完全没有图形环境,又不想装 X11 库,可以找带
nodisplay标识的编译版本,或者用xvfb-run包一层虚拟显示。但最省事的还是把运行库补齐。
2.3 环境变量:SACAUX、SACLIB 和 PATH 三件套
SAC 启动时会读三个关键环境变量。PATH让 shell 找到sac命令;SACAUX告诉它宏和辅助脚本在哪;SACLIB指向库目录。我一般直接写进~/.bashrc:
# SAC 101.5c 环境配置 export SAC_ROOT=/opt/sac export PATH=$SAC_ROOT/bin:$PATH export SACAUX=$SAC_ROOT/aux export SACLIB=$SAC_ROOT/lib写完source ~/.bashrc,然后which sac应该返回/opt/sac/bin/sac。这里有个容易忽略的点:如果你用的是zsh或csh,~/.bashrc不生效。SAC 老用户里用csh的不少,对应要写setenv SACAUX /opt/sac/aux这种语法。我见过有人在bash里配好了,一切到csh就报SACAUX not set,查了半天以为是包坏了,其实就是 shell 配置文件没对上。
3. 跑通第一个波形:从 sac 交互到宏脚本批处理
3.1 交互模式下读一个 SAC 文件并画图
环境配好后,终端敲sac回车,会看到提示符变成SAC>。这时候你已经进了交互模式。假设手头有个BHZ.sac波形文件,最小验证流程是:
SAC> r BHZ.sac # 读取波形 SAC> lh # 列出头段变量 SAC> bp c 0.5 5.0 # 带通滤波 0.5-5 Hz SAC> plot # 绘图 SAC> quit # 退出r是 read,lh是 list header,bp c是 bandpass corner 的缩写。这几条命令能跑通,说明二进制、库、数据读取链路全通了。如果r报ERROR 1301: No data files read in,八成是文件路径不对或者文件本身不是 SAC 格式。SAC 格式有固定二进制头段,用file BHZ.sac看应该显示data,如果显示ASCII text那就是文本格式,得先用sac的convert或外部工具转。
3.2 用宏脚本把重复操作固化下来
交互模式适合摸索,但真正干活得靠宏。SAC 宏就是一个纯文本文件,里面按行写命令,用m命令调用。比如把滤波、去均值、截窗、写出一整套流程写进proc.m:
# proc.m - 批量预处理宏 r $1 $2 # $1 $2 是调用时传入的文件名 rmean # 去均值 rtrend # 去线性趋势 bp c 0.5 5.0 # 带通滤波 w over # 覆盖写回调用方式是SAC> m proc.m BHZ.sac。注意宏里$1、$2是位置参数,SAC 宏不支持像 shell 那样的$@展开,参数个数得自己数清楚。我一般会在宏开头加一行echo打印当前处理文件,方便排查是哪个文件出的问题。宏的另一个坑是路径:宏里写的相对路径是相对于你启动sac时的当前目录,不是宏文件所在目录。所以要么用绝对路径,要么在启动前cd到数据目录。
3.3 批处理:用 shell 循环驱动 SAC
单个宏只能处理一个文件,几百个台站的数据得靠 shell 套。常见做法是写一个run_all.sh,遍历目录下所有.sac文件,每个文件调一次sac:
#!/bin/bash # 批量调用 SAC 处理目录下所有 sac 文件 for f in /data/waveforms/*.sac; do base=$(basename "$f") sac << EOF r $f rmean bp c 0.5 5.0 w over quit EOF echo "processed: $base" done这里用 heredoc 把命令喂给sac,比sac -c更直观。w over是覆盖写回原文件,如果你不想动原始数据,改成w /data/out/$base。批处理最怕的是某个文件损坏导致整个循环卡住,所以我在循环里加了echo进度,出问题时能立刻定位到是哪个文件。另外,SAC 每次启动都要读环境变量和初始化,几百个文件循环下来启动开销不小。如果数据量特别大,更好的做法是在一个sac会话里用m宏配合文件列表,而不是反复启停进程。
4. 参数与头段:SAC 处理里最容易翻车的地方
4.1 头段变量:时间、台站、分量
SAC 文件的头段(header)存了几十个变量,最核心的是kstnm(台站名)、kcmpnm(分量名)、knetwk(台网)、b(起始时间)、e(结束时间)、delta(采样间隔)、npts(点数)。这些变量决定了你后面所有时间窗操作能不能对上。我踩过最深的坑是b和e的时区问题:不同数据源导出的 SAC 文件,参考时间可能用 UTC 也可能用本地时,混在一起做互相关时差就全错了。处理前一定先lh b e kstnm看一眼,确认时间基准一致。
SAC> r BHZ.sac SAC> lh b e delta npts kstnm kcmpnm如果发现delta是 0 或者npts和文件实际大小对不上,说明头段损坏,这种文件直接跳过,别硬处理。delta为 0 会导致滤波时除零,SAC 可能不报错但结果全是 NaN,这种玄学问题查起来最费劲。
4.2 滤波参数:拐角频率和阶数怎么定
bp c f1 f2是最常用的带通,f1、f2是拐角频率。但很多人不知道 SAC 默认用的是 Butterworth 滤波器,阶数由bp后面的n参数控制,默认 2 阶。阶数越高过渡带越陡,但相位失真也越大。做波形互相关时我一般用 2 到 4 阶,做频谱分析才用更高阶。还有个隐藏参数是p(passes),默认单程,设成 2 就是零相位滤波(正反各滤一次),代价是计算量翻倍但相位不失真。
SAC> bp c 0.5 5.0 n 4 p 2 # 4阶零相位带通参数不是拍脑袋定的。拐角频率要落在信号有效频带内,比如远震 P 波主频在 0.5-2 Hz,你设 0.5-5 Hz 没问题;但如果是长周期面波,主频 0.02-0.1 Hz,用 0.5 Hz 做高通就把信号滤没了。我习惯先plot看原始波形,再fft看频谱,确认主频带后再定滤波参数。
4.3 时间窗与截取:cut 的边界处理
cut命令用来截取时间窗,语法是cut t1 t2或cut b e。这里有个反直觉的点:cut之后b会重置为 0,原来的绝对时间参考被丢弃。如果你后面还要用绝对时间做对齐,得先ch b <原值>把参考时间写回去,或者用cut的相对模式。我见过有人截窗后做互相关,结果所有台站时间都从 0 开始,互相关峰值全在 0 附近,完全没法用。正确做法是截窗前记下b,截窗后用ch b恢复,或者干脆用cut的t1 t2相对模式并保留原b。
注意:
cut默认会丢弃窗外数据,如果窗比数据长,SAC 会用零填充,填充部分参与滤波会产生边界效应。稳妥做法是截窗时留出滤波阶数对应的缓冲长度,滤完再截一次。
5. 避坑与排查:sac-101.5c 在 Linux 上的五类典型故障
5.1 启动报 libXm.so.4 not found
现象:敲sac直接报error while loading shared libraries: libXm.so.4: cannot open shared object file。原因是系统没装 Motif 运行库,SAC 的绘图模块依赖它。解决:CentOS 7 执行yum install openmotif,Debian/Ubuntu 执行apt install libxm4。装完用ldconfig刷新库缓存再试。如果还是没有,用find / -name "libXm.so*"确认装到哪了,必要时手动加LD_LIBRARY_PATH。
5.2 SACAUX 未设置导致宏命令失效
现象:sac能启动,但一执行m xxx.m就报ERROR 1001: Macro file not found,而文件明明存在。原因是SACAUX没设或指错,SAC 找不到宏搜索路径。解决:echo $SACAUX确认指向/opt/sac/aux,且该目录下有*.m文件。如果SACAUX设了但宏还是找不到,检查宏文件权限,SAC 对宏文件的可读性有要求,权限太严会静默失败。
5.3 读数据报 ERROR 1301
现象:r BHZ.sac报No data files read in。原因有三类:路径不对、文件不是 SAC 格式、文件头段损坏。排查顺序:先ls -l确认文件存在且非空;再file BHZ.sac看类型;最后用sac的read加more选项看详细报错。如果是格式问题,用sac自带的convert从 ASCII 转,或者用 ObsPy 这类 Python 库转成 SAC。头段损坏的文件基本救不回来,直接跳过。
5.4 批处理时内存暴涨
现象:shell 循环处理几百个文件,跑到一半机器开始 swap,甚至 OOM。原因是每次sac启动都会加载整套库和默认数据到内存,循环里进程没及时释放。解决:在循环里显式quit并加wait,或者改用单个sac会话配合文件列表。更彻底的做法是用sac的m宏一次读多个文件,SAC 内部会复用内存。我一般把批处理分成每 50 个文件一批,批间sleep 1给系统回收时间。
5.5 滤波结果全是 NaN
现象:bp之后plot出来一条直线,lh看数据全是 NaN。原因通常是delta为 0 或负值,导致滤波系数计算除零。解决:lh delta确认采样间隔,如果是 0,用ch delta <正确值>手动修正。另一个可能是数据里本身有 NaN 或 Inf,用sac的rmean前先mul 1检查,或者用cut去掉异常段。这类问题没有后悔药,只能处理前先做数据质检。
6. 进阶:用 SAC 宏 + shell 做可复现的波形预处理流水线
把前面所有东西串起来,我现在的标准做法是三层结构:底层是 SAC 宏,负责单文件的原子操作;中层是 shell 脚本,负责遍历和调度;顶层是一个config.sh,把所有参数(滤波频带、阶数、路径)集中管理。这样换一批数据只改config.sh,宏和调度脚本不动。
# config.sh - 集中参数 SAC_ROOT=/opt/sac DATA_DIR=/data/waveforms OUT_DIR=/data/processed BP_LOW=0.5 BP_HIGH=5.0 BP_ORDER=4# preprocess.m - 原子处理宏,参数从环境变量读 r $1 rmean rtrend bp c $BP_LOW $BP_HIGH n $BP_ORDER p 2 w $OUT_DIR/$2# run_pipeline.sh - 调度 source ./config.sh export SAC_ROOT DATA_DIR OUT_DIR BP_LOW BP_HIGH BP_ORDER export PATH=$SAC_ROOT/bin:$PATH export SACAUX=$SAC_ROOT/aux export SACLIB=$SAC_ROOT/lib mkdir -p $OUT_DIR for f in $DATA_DIR/*.sac; do base=$(basename "$f") sac << EOF m preprocess.m $f $base quit EOF done这套结构的好处是可复现:参数、宏、调度分离,换人换机器只要改config.sh就能跑出一样的结果。验证方法也简单,挑三个文件手动跑一遍宏,和流水线输出做diff,二进制一致就说明调度没问题。我现在的习惯是每次处理新数据集前,先拿三个文件跑通全流程,确认输出头段的b、e、delta和预期一致,再放开跑全量。这个习惯帮我省过好几次批量返工。希望帮到你。
本文还有配套的精品资源,点击获取