pax(Portable Archive eXchange)是一个跨平台的文件归档和交换工具,支持多种归档格式,可以在不同系统间传输文件,同时保留文件属性和权限。
pax是一个功能强大的归档工具:
| 特性 | pax | tar |
|---|---|---|
| 跨平台兼容性 | 优秀 | 良好 |
| 格式支持 | 多种格式 | 主要tar格式 |
| 标准支持 | POSIX标准 | 非标准 |
| 使用复杂度 | 较高 | 较低 |
pax [选项] [操作模式] [文件...]
# 三种基本操作模式:
# -r 读取模式(提取归档)
# -w 写入模式(创建归档)
# -r -w 复制模式(复制文件)
# 示例
pax -wf archive.tar file1 file2 # 创建归档
pax -rf archive.tar # 提取归档
pax -rw dir1 dir2 # 复制目录树
| 选项 | 说明 |
|---|---|
-r |
读取模式(从归档提取文件) |
-w |
写入模式(创建归档文件) |
-f 文件 |
指定归档文件名(默认为标准输入/输出) |
-v |
详细模式(显示处理文件) |
-x 格式 |
指定归档格式(如cpio, ustar, tar等) |
-a |
追加文件到现有归档 |
-c |
匹配除指定模式外的所有文件 |
-d |
仅匹配目录本身,不包含其内容 |
-p 权限 |
保留指定的文件属性(如mtime, atime等) |
-s 替换表达式 |
文件名替换(类似sed的s命令) |
-t |
保留文件访问时间 |
-u |
仅复制比目标新的文件 |
-z |
使用gzip压缩/解压(归档格式为tar时) |
-j |
使用bzip2压缩/解压 |
-o 选项 |
归档格式特定选项 |
创建归档文件:
提取归档文件:
复制文件树:
# 1. 基本创建归档
pax -wf archive.tar file1 file2 # 创建tar归档
pax -wf archive.tar * # 归档当前目录所有文件
# 2. 使用特定格式
pax -x cpio -wf archive.cpio file1 file2 # 创建cpio格式
pax -x ustar -wf archive.ustar . # 创建ustar格式
# 3. 使用压缩
pax -wf archive.tar.gz -z file1 file2 # 创建gzip压缩的tar
pax -wf archive.tar.bz2 -j file1 file2 # 创建bzip2压缩的tar
# 4. 详细模式查看过程
pax -vwf archive.tar file1 file2 dir1/
# 5. 从标准输入读取文件列表
find . -name "*.txt" | pax -wf textfiles.tar
# 6. 排除特定文件
find . -type f ! -name "*.tmp" | pax -wf notmp.tar
# 7. 保留文件属性
pax -wf archive.tar -p e file1 file2 # 保留所有属性
# 8. 创建增量备份(基于时间戳)
pax -wf backup.tar -T 20230101000000 . # 备份指定时间后的文件
# 9. 归档到远程服务器(通过ssh)
pax -wf - . | ssh user@host 'cat > backup.tar'
# 10. 分卷归档
pax -wf - . | split -b 100M - backup.tar.part
# 1. 基本提取
pax -rf archive.tar # 提取到当前目录
pax -rf archive.tar -C /tmp # 提取到指定目录
# 2. 提取特定格式
pax -rf archive.cpio -x cpio # 提取cpio格式
pax -rf archive.ustar -x ustar # 提取ustar格式
# 3. 解压缩提取
pax -rf archive.tar.gz -z # 提取gzip压缩的tar
pax -rf archive.tar.bz2 -j # 提取bzip2压缩的tar
# 4. 详细模式查看提取过程
pax -vrf archive.tar
# 5. 选择性提取
pax -rf archive.tar file1 # 只提取file1
pax -rf archive.tar "*.txt" # 只提取txt文件
# 6. 保留文件属性
pax -rf archive.tar -p e # 保留所有属性
# 7. 不覆盖已存在文件
pax -rf archive.tar -k # -k选项防止覆盖
# 8. 从标准输入读取归档
cat archive.tar | pax -rf - # 从stdin读取
ssh user@host 'cat backup.tar' | pax -rf - # 从远程提取
# 9. 列出归档内容而不提取
pax -f archive.tar # 列出归档内容
pax -vf archive.tar # 详细列出
# 10. 提取并重命名文件
pax -rf archive.tar -s '|oldname|newname|' # 重命名提取的文件
# 1. 基本目录复制
pax -rw dir1 dir2 # 复制dir1到dir2
pax -rw source destination # 复制source到destination
# 2. 保留文件属性
pax -rw -p e source destination # 保留所有属性
pax -rw -p m source destination # 保留修改时间
# 3. 详细模式复制
pax -rwv source destination # 显示复制过程
# 4. 仅复制新文件
pax -rwu source destination # 仅复制比目标新的文件
# 5. 排除特定文件
find source -type f ! -name "*.tmp" | pax -rw -d destination
# 6. 跨文件系统复制
pax -rw -pe source /mnt/backup # 保留属性跨文件系统
# 7. 复制并重命名
pax -rw source destination -s '|source/|dest/|' # 路径重命名
# 8. 复制到远程服务器
pax -rw . -s ',.*/,,' | ssh user@host 'cd /backup && pax -r'
# 9. 增量备份复制
pax -rw -T 20230101000000 source destination # 复制指定时间后的文件
# 10. 复制权限和所有权(需要root)
sudo pax -rw -p p source destination # 保留所有权
# 11. 比较复制(显示差异)
pax -rw -v source destination | grep -v "skipped"
# 12. 复制特定文件类型
find source -name "*.txt" -o -name "*.pdf" | pax -rw -d destination
# 13. 创建硬链接而不是复制
# pax本身不支持硬链接,但可以结合find
cd source && find . -type f -exec ln {} ../destination/{} \;
# 14. 复制大量文件(比cp更稳定)
pax -rw -p e /source/large_dir /destination/
| 格式 | 选项 | 说明 | 常见扩展名 |
|---|---|---|---|
| cpio | -x cpio |
旧的Unix归档格式,支持设备文件 | .cpio, .cpio.gz |
| ustar | -x ustar |
POSIX tar格式(推荐) | .tar, .tar.gz |
| tar | -x tar |
传统tar格式 | .tar, .tar.Z |
| sv4cpio | -x sv4cpio |
System V Release 4 cpio | .cpio |
| sv4crc | -x sv4crc |
带CRC校验的System V cpio | .cpio |
ustar格式(POSIX标准)cpio格式tar格式(最广泛支持)sv4crc格式-z(gzip)或-j(bzip2)#!/bin/bash
# 完整的备份和恢复脚本
# 文件名:pax_backup_system.sh
BACKUP_DIR="/backup"
LOG_FILE="/var/log/pax_backup.log"
CONFIG_FILE="/etc/backup.conf"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color
# 日志函数
log() {
local level="$1"
local message="$2"
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}
# 初始化备份环境
init_backup() {
log "INFO" "初始化备份环境"
# 创建备份目录
mkdir -p "$BACKUP_DIR"/{daily,weekly,monthly}
# 检查pax命令
if ! command -v pax &> /dev/null; then
log "ERROR" "pax命令未找到,请安装"
exit 1
fi
# 加载配置文件
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
else
# 默认配置
BACKUP_SOURCES=(
"/etc"
"/home"
"/var/www"
"/opt"
)
BACKUP_EXCLUDES=(
"*.tmp"
"*.log"
"*.cache"
)
RETENTION_DAYS=30
fi
log "INFO" "备份环境初始化完成"
}
# 创建完整备份
create_full_backup() {
local backup_name="full_backup_$(date +%Y%m%d_%H%M%S).tar.gz"
local backup_path="$BACKUP_DIR/monthly/$backup_name"
log "INFO" "开始创建完整备份: $backup_name"
# 创建排除文件列表
local exclude_file="/tmp/exclude_$$.txt"
for pattern in "${BACKUP_EXCLUDES[@]}"; do
echo "$pattern" >> "$exclude_file"
done
# 使用pax创建备份
log "INFO" "收集备份文件..."
find "${BACKUP_SOURCES[@]}" -type f ! -name "*.tmp" ! -name "*.log" 2>/dev/null | \
pax -wzf "$backup_path" -d -s "|^/||"
if [ $? -eq 0 ]; then
local size=$(du -h "$backup_path" | cut -f1)
log "SUCCESS" "完整备份创建完成: $backup_name ($size)"
# 创建校验文件
md5sum "$backup_path" > "$backup_path.md5"
else
log "ERROR" "完整备份创建失败"
fi
# 清理
rm -f "$exclude_file"
}
# 创建增量备份
create_incremental_backup() {
local backup_name="inc_backup_$(date +%Y%m%d_%H%M%S).tar.gz"
local backup_path="$BACKUP_DIR/daily/$backup_name"
local last_backup=$(find "$BACKUP_DIR" -name "*.tar.gz" -type f -printf "%T@ %p\n" | sort -nr | head -1 | cut -d' ' -f2)
log "INFO" "开始创建增量备份: $backup_name"
if [ -z "$last_backup" ]; then
log "WARNING" "未找到之前的备份,创建完整备份"
create_full_backup
return
fi
# 获取上次备份时间
local last_time=$(stat -c %Y "$last_backup")
# 查找上次备份后修改的文件
log "INFO" "查找自上次备份后修改的文件..."
find "${BACKUP_SOURCES[@]}" -type f -newer "@$last_time" ! -name "*.tmp" ! -name "*.log" 2>/dev/null | \
pax -wzf "$backup_path" -d -s "|^/||"
if [ $? -eq 0 ]; then
local size=$(du -h "$backup_path" | cut -f1)
local file_count=$(pax -tzf "$backup_path" | wc -l)
log "SUCCESS" "增量备份创建完成: $backup_name ($size, $file_count 个文件)"
else
log "ERROR" "增量备份创建失败"
fi
}
# 恢复备份
restore_backup() {
local backup_file="$1"
local restore_path="${2:-/}"
if [ ! -f "$backup_file" ]; then
log "ERROR" "备份文件不存在: $backup_file"
return 1
fi
log "INFO" "开始恢复备份: $(basename "$backup_file")"
log "INFO" "恢复到: $restore_path"
# 验证备份文件
if [ -f "$backup_file.md5" ]; then
if ! md5sum -c "$backup_file.md5" &> /dev/null; then
log "ERROR" "备份文件校验失败,可能已损坏"
return 1
fi
fi
# 交互式确认
read -p "确认恢复备份?这将覆盖现有文件。 (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log "INFO" "恢复操作已取消"
return 0
fi
# 执行恢复
log "INFO" "正在恢复文件..."
if pax -rzf "$backup_file" -C "$restore_path" -p e; then
log "SUCCESS" "备份恢复完成"
# 恢复文件权限
log "INFO" "修复文件权限..."
restore_permissions "$backup_file" "$restore_path"
else
log "ERROR" "备份恢复失败"
return 1
fi
}
# 恢复文件权限
restore_permissions() {
local backup_file="$1"
local restore_path="$2"
log "INFO" "从备份中提取权限信息..."
# 创建临时目录存放权限信息
local temp_dir="/tmp/restore_perms_$$"
mkdir -p "$temp_dir"
# 提取包含权限信息的文件列表
pax -tzvf "$backup_file" | awk '{print $6, $3, $4, $1}' > "$temp_dir/filelist.txt"
# 应用权限
while read -r file mode owner group; do
# 移除开头的./
file="${file#./}"
if [ -f "$restore_path/$file" ]; then
# 设置权限
chmod "$mode" "$restore_path/$file" 2>/dev/null || true
# 设置所有者和组(需要root权限)
if [ $(id -u) -eq 0 ]; then
chown "$owner:$group" "$restore_path/$file" 2>/dev/null || true
fi
fi
done < "$temp_dir/filelist.txt"
rm -rf "$temp_dir"
log "INFO" "权限恢复完成"
}
# 清理旧备份
cleanup_old_backups() {
log "INFO" "清理旧备份文件"
# 清理daily备份(保留7天)
find "$BACKUP_DIR/daily" -name "*.tar.gz" -mtime +7 -delete
find "$BACKUP_DIR/daily" -name "*.md5" -mtime +7 -delete
# 清理weekly备份(保留30天)
find "$BACKUP_DIR/weekly" -name "*.tar.gz" -mtime +30 -delete
find "$BACKUP_DIR/weekly" -name "*.md5" -mtime +30 -delete
# 清理monthly备份(保留365天)
find "$BACKUP_DIR/monthly" -name "*.tar.gz" -mtime +365 -delete
find "$BACKUP_DIR/monthly" -name "*.md5" -mtime +365 -delete
log "INFO" "旧备份清理完成"
}
# 列出可用备份
list_backups() {
echo "=== 可用备份 ==="
echo ""
echo "月度备份:"
find "$BACKUP_DIR/monthly" -name "*.tar.gz" -type f -printf " %f (%TY-%Tm-%Td %TH:%TM)\n" 2>/dev/null | sort -r
echo ""
echo "周度备份:"
find "$BACKUP_DIR/weekly" -name "*.tar.gz" -type f -printf " %f (%TY-%Tm-%Td %TH:%TM)\n" 2>/dev/null | sort -r
echo ""
echo "每日备份:"
find "$BACKUP_DIR/daily" -name "*.tar.gz" -type f -printf " %f (%TY-%Tm-%Td %TH:%TM)\n" 2>/dev/null | sort -r
}
# 主菜单
main_menu() {
init_backup
while true; do
echo ""
echo "=== PAX备份管理系统 ==="
echo "1. 创建完整备份"
echo "2. 创建增量备份"
echo "3. 恢复备份"
echo "4. 列出所有备份"
echo "5. 清理旧备份"
echo "6. 查看备份日志"
echo "7. 退出"
echo -n "请选择 [1-7]: "
read -r choice
case $choice in
1)
create_full_backup
;;
2)
create_incremental_backup
;;
3)
echo "可用的备份文件:"
find "$BACKUP_DIR" -name "*.tar.gz" -type f | nl
echo -n "请输入备份编号: "
read -r backup_num
backups=($(find "$BACKUP_DIR" -name "*.tar.gz" -type f | sort))
selected="${backups[$((backup_num-1))]}"
if [ -n "$selected" ]; then
echo -n "请输入恢复路径 (默认: /): "
read -r restore_path
restore_backup "$selected" "${restore_path:-/}"
else
echo "无效的选择"
fi
;;
4)
list_backups
;;
5)
cleanup_old_backups
;;
6)
echo "=== 备份日志 ==="
tail -50 "$LOG_FILE"
;;
7)
echo "退出"
exit 0
;;
*)
echo "无效选择"
;;
esac
echo ""
read -p "按回车键继续..." -n1
clear
done
}
# 运行主菜单
main_menu
#!/bin/bash
# 跨平台文件传输工具
# 文件名:cross_platform_transfer.sh
SOURCE_HOST=""
SOURCE_PATH=""
DEST_HOST=""
DEST_PATH=""
TRANSFER_MODE="archive" # archive, copy, sync
ARCHIVE_FORMAT="ustar"
COMPRESSION="gzip"
PRESERVE_ATTRS=true
VERBOSE=false
# 显示帮助
show_help() {
cat << EOF
跨平台文件传输工具
使用方法: $0 [选项]
选项:
-s, --source HOST:PATH 源主机和路径(本地路径不需要主机)
-d, --dest HOST:PATH 目标主机和路径
-m, --mode MODE 传输模式: archive, copy, sync (默认: archive)
-f, --format FORMAT 归档格式: ustar, cpio, tar (默认: ustar)
-c, --compress TYPE 压缩类型: gzip, bzip2, none (默认: gzip)
-p, --preserve 保留文件属性(默认: 是)
-n, --no-preserve 不保留文件属性
-v, --verbose 详细输出
-h, --help 显示此帮助信息
示例:
# 本地到本地归档传输
$0 -s /local/path -d /backup/path
# 本地到远程传输
$0 -s /local/path -d user@remote:/remote/path
# 远程到本地传输
$0 -s user@remote:/remote/path -d /local/path
# 同步模式
$0 -s /source -d /dest -m sync -p
EOF
}
# 解析命令行参数
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
-s|--source)
SOURCE="$2"
# 解析主机和路径
if [[ "$SOURCE" == *:* ]]; then
SOURCE_HOST="${SOURCE%%:*}"
SOURCE_PATH="${SOURCE#*:}"
else
SOURCE_HOST="localhost"
SOURCE_PATH="$SOURCE"
fi
shift 2
;;
-d|--dest)
DEST="$2"
if [[ "$DEST" == *:* ]]; then
DEST_HOST="${DEST%%:*}"
DEST_PATH="${DEST#*:}"
else
DEST_HOST="localhost"
DEST_PATH="$DEST"
fi
shift 2
;;
-m|--mode)
TRANSFER_MODE="$2"
shift 2
;;
-f|--format)
ARCHIVE_FORMAT="$2"
shift 2
;;
-c|--compress)
COMPRESSION="$2"
shift 2
;;
-p|--preserve)
PRESERVE_ATTRS=true
shift
;;
-n|--no-preserve)
PRESERVE_ATTRS=false
shift
;;
-v|--verbose)
VERBOSE=true
shift
;;
-h|--help)
show_help
exit 0
;;
*)
echo "未知选项: $1"
show_help
exit 1
;;
esac
done
# 验证参数
if [ -z "$SOURCE_PATH" ] || [ -z "$DEST_PATH" ]; then
echo "错误: 必须指定源路径和目标路径"
show_help
exit 1
fi
}
# 执行SSH命令
ssh_cmd() {
local host="$1"
local cmd="$2"
if [ "$host" = "localhost" ]; then
eval "$cmd"
else
ssh "$host" "$cmd"
fi
}
# 检查远程主机是否可用
check_host() {
local host="$1"
if [ "$host" != "localhost" ]; then
echo "检查主机连接: $host"
if ! ssh -o ConnectTimeout=5 "$host" "echo '连接成功'" &> /dev/null; then
echo "错误: 无法连接到主机 $host"
return 1
fi
fi
return 0
}
# 归档模式传输
transfer_archive() {
echo "使用归档模式传输"
echo "源: $SOURCE_HOST:$SOURCE_PATH"
echo "目标: $DEST_HOST:$DEST_PATH"
echo "格式: $ARCHIVE_FORMAT"
echo "压缩: $COMPRESSION"
# 构建pax命令选项
local pax_opts="-x $ARCHIVE_FORMAT"
if [ "$PRESERVE_ATTRS" = true ]; then
pax_opts="$pax_opts -p e"
fi
if [ "$VERBOSE" = true ]; then
pax_opts="$pax_opts -v"
fi
# 压缩选项
local compress_opts=""
case "$COMPRESSION" in
gzip)
compress_opts="-z"
;;
bzip2)
compress_opts="-j"
;;
none)
compress_opts=""
;;
esac
# 创建临时文件
local temp_file="/tmp/transfer_$$.tar"
# 从源读取并归档
echo "正在从源读取文件..."
if [ "$SOURCE_HOST" = "localhost" ]; then
cd "$SOURCE_PATH" || { echo "错误: 无法进入源目录"; return 1; }
pax -w $pax_opts $compress_opts -f "$temp_file" .
else
ssh_cmd "$SOURCE_HOST" "cd '$SOURCE_PATH' && pax -w $pax_opts $compress_opts" > "$temp_file"
fi
if [ $? -ne 0 ]; then
echo "错误: 创建归档失败"
rm -f "$temp_file"
return 1
fi
# 传输到目标
echo "正在传输到目标..."
local file_size=$(du -h "$temp_file" | cut -f1)
echo "归档大小: $file_size"
if [ "$DEST_HOST" = "localhost" ]; then
# 确保目标目录存在
mkdir -p "$DEST_PATH"
# 提取到目标
pax -r $pax_opts $compress_opts -f "$temp_file" -C "$DEST_PATH"
else
# 传输到远程并提取
cat "$temp_file" | ssh_cmd "$DEST_HOST" "mkdir -p '$DEST_PATH' && cd '$DEST_PATH' && pax -r $pax_opts $compress_opts"
fi
if [ $? -eq 0 ]; then
echo "传输完成"
else
echo "错误: 提取归档失败"
fi
# 清理临时文件
rm -f "$temp_file"
}
# 复制模式传输
transfer_copy() {
echo "使用复制模式传输"
# 构建pax命令选项
local pax_opts="-rw"
if [ "$PRESERVE_ATTRS" = true ]; then
pax_opts="$pax_opts -p e"
fi
if [ "$VERBOSE" = true ]; then
pax_opts="$pax_opts -v"
fi
# 检查源和目标是否在同一主机
if [ "$SOURCE_HOST" = "$DEST_HOST" ]; then
# 本地复制
if [ "$SOURCE_HOST" = "localhost" ]; then
echo "执行本地复制..."
pax $pax_opts "$SOURCE_PATH" "$DEST_PATH"
else
# 远程主机内复制
echo "在远程主机 $SOURCE_HOST 内复制..."
ssh_cmd "$SOURCE_HOST" "pax $pax_opts '$SOURCE_PATH' '$DEST_PATH'"
fi
else
echo "错误: 复制模式不支持跨主机传输"
echo "请使用归档模式 (-m archive)"
return 1
fi
}
# 同步模式传输
transfer_sync() {
echo "使用同步模式传输"
# 同步模式实际上是复制模式的增量版本
local pax_opts="-rwu" # -u 只复制更新的文件
if [ "$PRESERVE_ATTRS" = true ]; then
pax_opts="$pax_opts -p e"
fi
if [ "$VERBOSE" = true ]; then
pax_opts="$pax_opts -v"
fi
if [ "$SOURCE_HOST" = "$DEST_HOST" ]; then
# 本地同步
if [ "$SOURCE_HOST" = "localhost" ]; then
echo "执行本地同步..."
pax $pax_opts "$SOURCE_PATH" "$DEST_PATH"
else
# 远程主机内同步
echo "在远程主机 $SOURCE_HOST 内同步..."
ssh_cmd "$SOURCE_HOST" "pax $pax_opts '$SOURCE_PATH' '$DEST_PATH'"
fi
else
echo "错误: 同步模式不支持跨主机传输"
echo "请使用归档模式 (-m archive)"
return 1
fi
}
# 主函数
main() {
parse_args "$@"
echo "=== 跨平台文件传输工具 ==="
echo ""
# 检查主机连接
check_host "$SOURCE_HOST" || exit 1
check_host "$DEST_HOST" || exit 1
# 执行传输
case "$TRANSFER_MODE" in
archive)
transfer_archive
;;
copy)
transfer_copy
;;
sync)
transfer_sync
;;
*)
echo "错误: 未知的传输模式: $TRANSFER_MODE"
exit 1
;;
esac
echo ""
echo "传输完成"
}
# 运行主函数
main "$@"
# 错误:bash: pax: command not found
# 原因:pax命令未安装
# 解决方案:
# 1. 检查是否已安装
which pax
pax --version
# 2. 安装pax(不同Linux发行版)
# Debian/Ubuntu:
sudo apt-get update
sudo apt-get install pax
# CentOS/RHEL:
sudo yum install pax
# Fedora:
sudo dnf install pax
# Arch Linux:
sudo pacman -S pax
# 3. 如果无法安装pax,使用tar替代
# pax常用功能tar基本都支持
# 4. 检查PATH环境变量
echo $PATH
# 确保/usr/bin在PATH中
# 5. 从源码编译安装
# 下载源码:ftp://ftp.suse.com/pub/people/kukuk/pax/
# 编译安装:
tar xzf pax-*.tar.gz
cd pax-*
./configure
make
sudo make install
# 6. 验证安装
pax -w . | pax -r -v 2>/dev/null
# 如果正常,说明pax工作正常
# 错误:pax: Invalid header, archive corrupted
# 原因:归档文件损坏或格式不匹配
# 解决方案:
# 1. 检查归档文件完整性
file archive.tar
# 输出应为:POSIX tar archive
# 2. 尝试列出归档内容
pax -f archive.tar
# 或
pax < archive.tar
# 3. 使用不同格式尝试
pax -f archive.tar -x tar
pax -f archive.tar -x ustar
pax -f archive.tar -x cpio
# 4. 检查文件大小
ls -lh archive.tar
# 如果大小为0,文件可能损坏
# 5. 使用dd尝试修复
dd if=archive.tar of=archive_fixed.tar conv=sync,noerror
# 6. 从备份恢复
# 如果有备份,重新获取归档文件
# 7. 使用其他工具尝试
tar -tf archive.tar # 使用tar列出
cpio -t < archive.cpio # 使用cpio列出
# 8. 检查磁盘错误
fsck /dev/sda1 # 检查文件系统
badblocks -v /dev/sda1 # 检查坏块
# 9. 验证归档创建过程
# 重新创建归档并验证
pax -wf test.tar .
pax -rf test.tar -C /tmp/test
diff -r . /tmp/test
# 10. 使用压缩时检查
# 如果是压缩归档,先解压再测试
gzip -t archive.tar.gz # 测试gzip文件
bzip2 -t archive.tar.bz2 # 测试bzip2文件
# 错误:pax: Cannot open: Permission denied
# 原因:权限不足无法读取/写入文件
# 解决方案:
# 1. 检查文件权限
ls -la 文件名
# 需要读取权限(r)来归档,写入权限(w)来提取
# 2. 使用sudo(如果需要)
sudo pax -wf archive.tar /etc
sudo pax -rf archive.tar -C /root
# 3. 检查磁盘空间
df -h .
# 确保有足够空间创建归档
# 4. 检查文件所有权
# 如果文件属于其他用户,可能需要sudo
sudo pax -wf archive.tar /home/otheruser
# 5. 使用-p选项处理权限
pax -wf archive.tar -p p . # 保留所有权(需要root)
# 6. 避免权限问题的方法
# 创建归档时不包含权限信息
pax -wf archive.tar -p "" .
# 7. 检查SELinux/AppArmor
# 这些安全模块可能阻止访问
getenforce # 检查SELinux状态
# 如果是Enforcing模式,尝试
sudo setenforce 0 # 临时禁用(测试用)
# 8. 检查文件系统挂载选项
# 某些文件系统可能以只读方式挂载
mount | grep " / "
# 如果是ro,重新挂载为rw
sudo mount -o remount,rw /
# 9. 使用find排除权限问题文件
find . -type f -readable | pax -wf archive.tar
# 10. 创建用户可访问的临时目录
mkdir -p /tmp/mybackup
cp -a 文件 /tmp/mybackup/
pax -wf archive.tar /tmp/mybackup
# 问题:在Linux上创建的归档在Solaris/AIX上无法读取
# 原因:平台差异和格式兼容性问题
# 解决方案:
# 1. 使用最兼容的格式
pax -x ustar -wf archive.tar . # ustar是POSIX标准
# 2. 避免使用平台特定功能
# 不使用扩展属性、ACL等
# 3. 文件名长度限制
# 传统tar限制文件名100字符,ustar限制256字符
# 使用find检查长文件名
find . -name "*" | awk 'length($0) > 100'
# 4. 特殊字符处理
# 避免使用换行符等特殊字符
find . -name "*" -print0 | pax -0 -wf archive.tar
# 5. 文件类型兼容性
# 某些平台不支持某些文件类型(如FIFO、设备文件)
# 使用-type f只归档普通文件
find . -type f | pax -wf archive.tar
# 6. 时间戳格式
# 使用-p m保留修改时间
pax -wf archive.tar -p m .
# 7. 符号链接处理
# 默认会归档链接目标,使用-L跟随链接
pax -wf archive.tar -L . # 归档链接指向的文件
# 8. 大文件支持
# 确保使用支持大文件的格式
pax -x ustar -wf archive.tar . # ustar支持最大8GB文件
# 9. 字符编码
# 确保文件名使用ASCII字符
# 非ASCII字符可能在不同平台有问题
# 10. 测试跨平台兼容性
# 创建测试归档
pax -x ustar -wf test.tar .
# 在目标平台测试
pax -rf test.tar
# 比较文件差异
pax -wf 归档.tar 文件 - 创建归档pax -rf 归档.tar - 提取归档pax -f 归档.tar - 列出内容pax -rw 源 目标 - 复制目录树-v - 详细输出-z - gzip压缩-j - bzip2压缩-p e - 保留所有属性-x ustar # POSIX标准tar(推荐)
-x cpio # 传统cpio格式
-x tar # 传统tar格式
-x sv4crc # 带CRC校验的System V格式
ustar格式(-x ustar)-p e保留所有文件属性-z或-j压缩减少大小pax -t)