Linux smbclient命令

smbclient 是一个功能强大的SMB/CIFS客户端工具,允许Linux系统访问和操作Windows共享、Samba服务器和其他支持SMB/CIFS协议的网络共享。它提供了一个类似FTP的交互式界面,支持文件传输、共享浏览和基本管理操作。

注意:smbclient是Samba软件套件的一部分,Samba是开源软件,实现了SMB/CIFS协议,允许Linux/Unix系统与Windows系统进行文件和打印机共享。

安装smbclient

在基于Debian/Ubuntu的系统上安装:

sudo apt-get update
sudo apt-get install samba-client samba-common

在基于RHEL/CentOS的系统上安装:

sudo yum install samba-client
# 或者
sudo dnf install samba-client

在基于Arch Linux的系统上安装:

sudo pacman -S samba

在基于macOS的系统上安装(通过Homebrew):

brew install samba

语法格式

smbclient [选项] 服务位置 [密码] [子命令]

或者交互式模式:

smbclient //服务器/共享名 [选项]

常用选项

选项 说明
-L, --list=主机 列出指定主机的可用共享
-U, --user=用户名[%密码] 指定用户名和密码
-W, --workgroup=工作组 指定工作组/域
-I, --ip-address=IP 指定服务器的IP地址
-N, --no-pass 不使用密码,匿名访问
-A, --authentication-file=文件 从文件读取用户名和密码
-c, --command=命令 执行命令后退出(非交互模式)
-t, --timeout=秒 设置操作超时时间
-p, --port=端口 指定SMB端口(默认445)
-d, --debuglevel=级别 设置调试级别(0-10)
-s, --configfile=文件 指定配置文件
-m, --max-protocol=协议 指定最大协议版本
-e, --encrypt 使用加密传输
-M, --message=主机 发送WinPopup消息
--help 显示帮助信息
--version 显示版本信息

基本使用示例

示例1:列出远程主机的共享

列出指定Windows主机或Samba服务器的可用共享:

# 匿名列出共享
smbclient -L //192.168.1.100 -N

# 使用用户名列出共享
smbclient -L //192.168.1.100 -U username

# 指定用户名和密码
smbclient -L //192.168.1.100 -U username%password

# 指定工作组
smbclient -L //WINSERVER -W WORKGROUP -U username%password

输出示例:

Sharename       Type      Comment
---------       ----      -------
ADMIN$          Disk      远程管理
C$              Disk      默认共享
IPC$            IPC       远程 IPC
Public          Disk      公共共享
Users           Disk      用户目录
Reconnecting with SMB1 for workgroup listing.
Server               Comment
---------            -------
WINSERVER

Workgroup            Master
---------            -------
WORKGROUP           WINSERVER

示例2:连接共享目录(交互式模式)

# 连接共享目录
smbclient //192.168.1.100/Public -U username%password

# 连接后进入smb: \>提示符
# 可以执行各种命令,如ls、get、put等

示例3:连接共享目录(非交互式模式)

# 执行单个命令后退出
smbclient //192.168.1.100/Public -U username%password -c "ls"

# 执行多个命令
smbclient //192.168.1.100/Public -U username%password -c "ls; get file.txt; exit"

示例4:匿名访问共享

# 尝试匿名访问
smbclient //192.168.1.100/Public -N

# 匿名列出共享
smbclient -L //192.168.1.100 -N

smbclient交互式命令

连接共享后进入交互式模式,可用命令:

命令 说明
help [命令] 显示帮助信息
? 同help
ls [目录] 列出目录内容
dir [目录] 同ls
cd [目录] 切换目录
lcd [目录] 切换本地目录
pwd 显示当前远程目录
lpwd 显示当前本地目录
get 远程文件 [本地文件] 下载文件
put 本地文件 [远程文件] 上传文件
mget 模式 批量下载匹配文件
mput 模式 批量上传匹配文件
mkdir 目录 创建目录
rmdir 目录 删除目录
rm 文件 删除文件
del 文件 同rm
rename 旧文件 新文件 重命名文件
more 文件 查看文件内容
mask 模式 设置文件掩码(通配符)
recurse 切换递归模式(目录操作)
prompt 切换交互提示(批量操作时)
queue 显示操作队列
quit 退出smbclient
exit 同quit
tar c|x [IXbgNa] tar备份/恢复
blocksize 大小 设置块大小
tarmode 模式 设置tar模式
setmode 文件 模式 设置文件属性

交互式使用示例

示例5:完整的交互式会话

# 连接共享
smbclient //192.168.1.100/Public -U username%password

# 连接成功后的交互操作示例:
smb: \> help              # 显示帮助
smb: \> ls                # 列出文件
smb: \> cd Documents      # 进入Documents目录
smb: \> pwd               # 显示当前目录
smb: \> lcd ~/downloads   # 切换本地目录
smb: \> lpwd              # 显示本地目录
smb: \> get report.pdf    # 下载文件
smb: \> put local.txt     # 上传文件
smb: \> mkdir newdir      # 创建目录
smb: \> rename old new    # 重命名文件
smb: \> rm temp.txt       # 删除文件
smb: \> mget *.txt        # 下载所有txt文件
smb: \> mput *.pdf        # 上传所有pdf文件
smb: \> recurse on        # 开启递归模式
smb: \> prompt off        # 关闭提示(批量操作)
smb: \> quit              # 退出

示例6:批量下载文件

# 非交互式批量下载
smbclient //192.168.1.100/Public -U username%password -c "prompt; mget *.pdf; exit"

# 或交互式操作
smb: \> prompt
smb: \> mget *.pdf
smb: \> quit

示例7:递归下载目录

# 递归下载整个目录
smb: \> tar c Documents
# 这会创建一个名为Documents.tar的tar备份

# 恢复tar备份
smb: \> tar x backup.tar

配置文件

smbclient可以使用以下配置文件:

配置文件 位置 说明
全局配置 /etc/samba/smb.conf Samba主配置文件
用户配置 ~/.smb/smb.conf 用户级配置文件
凭据文件 ~/.smbcredentials 存储用户名和密码
主机缓存 ~/.smbhosts 主机名缓存

创建凭据文件

# 创建凭据文件
nano ~/.smbcredentials
# 内容:
username=myusername
password=mypassword
domain=WORKGROUP

# 设置权限
chmod 600 ~/.smbcredentials

# 使用凭据文件
smbclient //server/share -A ~/.smbcredentials

示例smb.conf配置

[global]
    workgroup = WORKGROUP
    client min protocol = NT1
    client max protocol = SMB3
    client lanman auth = yes
    client ntlmv2 auth = yes

[homes]
    comment = Home Directories
    browseable = no
    read only = no
    create mask = 0700
    directory mask = 0700

实际应用场景

场景1:自动备份Windows共享文件

#!/bin/bash
# backup_windows_share.sh - 自动备份Windows共享

SERVER="192.168.1.100"
SHARE="Backup"
USERNAME="backupuser"
PASSWORD="password123"
LOCAL_DIR="/backup/windows"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="windows_backup_$DATE.tar.gz"

echo "开始备份Windows共享..."
echo "服务器: $SERVER"
echo "共享: $SHARE"
echo "时间: $DATE"

# 创建本地目录
mkdir -p "$LOCAL_DIR"

# 使用smbclient创建tar备份
smbclient "//$SERVER/$SHARE" -U "$USERNAME%$PASSWORD" -c "tar c *" | \
gzip > "$LOCAL_DIR/$BACKUP_FILE"

if [ $? -eq 0 ]; then
    echo "备份成功: $BACKUP_FILE"
    echo "大小: $(du -h "$LOCAL_DIR/$BACKUP_FILE" | cut -f1)"
else
    echo "备份失败"
    exit 1
fi

# 清理旧备份(保留最近7天)
find "$LOCAL_DIR" -name "windows_backup_*.tar.gz" -mtime +7 -delete
echo "已清理7天前的旧备份"

场景2:同步Windows共享到Linux

#!/bin/bash
# sync_windows_share.sh - 同步Windows共享

SERVER="192.168.1.100"
SHARE="Documents"
USERNAME="syncuser"
PASSWORD="syncpass123"
LOCAL_DIR="/data/sync/$SHARE"
REMOTE_DIR="/"
LOG_FILE="/var/log/sync_windows.log"

echo "$(date) 开始同步 $SHARE" >> "$LOG_FILE"

# 创建本地目录
mkdir -p "$LOCAL_DIR"

# 同步文件
smbclient "//$SERVER/$SHARE" -U "$USERNAME%$PASSWORD" -c "
    prompt
    recurse
    mask *.pdf,*.doc,*.docx,*.xls,*.xlsx,*.ppt,*.pptx
    lcd $LOCAL_DIR
    mget *
" >> "$LOG_FILE" 2>&1

if [ $? -eq 0 ]; then
    echo "$(date) 同步成功" >> "$LOG_FILE"
    echo "同步的文件数: $(find "$LOCAL_DIR" -type f | wc -l)" >> "$LOG_FILE"
else
    echo "$(date) 同步失败" >> "$LOG_FILE"
fi

场景3:发送WinPopup消息

# 发送消息到Windows计算机
smbclient -M WINDOWS_PC << EOF
From: Linux Server
Subject: 服务器通知
正文:服务器将于今晚10点进行维护,请保存工作。

EOF

# 或使用单行命令
echo -e "From: Admin\n\n系统维护通知" | smbclient -M COMPUTER_NAME

故障排除

问题1:连接被拒绝

session setup failed: NT_STATUS_LOGON_FAILURE

解决方案:

# 1. 检查用户名和密码
smbclient //server/share -U username%password

# 2. 检查工作组/域
smbclient //server/share -U username%password -W DOMAIN

# 3. 使用IP地址代替主机名
smbclient //192.168.1.100/share -U username%password

# 4. 检查防火墙设置
# Windows: 确保文件和打印机共享被允许
# Linux: sudo ufw allow samba

# 5. 检查SMB协议版本
smbclient //server/share -U username%password -m SMB2
smbclient //server/share -U username%password -m NT1

问题2:无法列出共享

tree connect failed: NT_STATUS_BAD_NETWORK_NAME

解决方案:

# 1. 检查共享名是否正确
smbclient -L //server -U username%password

# 2. 共享可能需要完整路径
smbclient //server/C$/Windows -U username%password

# 3. 尝试使用管理员共享
smbclient //server/ADMIN$ -U administrator%password

# 4. 检查共享权限

问题3:连接超时

Connection to SERVER failed (Error NT_STATUS_CONNECTION_REFUSED)

解决方案:

# 1. 检查网络连通性
ping 192.168.1.100

# 2. 检查SMB端口
telnet 192.168.1.100 445
telnet 192.168.1.100 139

# 3. 增加超时时间
smbclient //server/share -U username%password -t 60

# 4. 使用WINS服务器
smbclient //server/share -U username%password -W WORKGROUP

问题4:权限问题

NT_STATUS_ACCESS_DENIED listing \*

解决方案:

# 1. 检查用户权限
# 确保用户有访问共享的权限

# 2. 使用不同用户
smbclient //server/share -U administrator%password

# 3. 检查共享权限设置
# Windows: 右键共享 -> 属性 -> 共享权限/安全权限

调试和日志

启用调试模式

# 启用详细调试
smbclient //server/share -U username%password -d 3

# 调试级别说明:
# 0: 无调试
# 1: 基本调试
# 2: 详细调试
# 3: 非常详细
# 4: 调试所有

# 保存调试日志到文件
smbclient //server/share -U username%password -d 3 2>&1 | tee debug.log

查看Samba日志

# 查看Samba日志
sudo tail -f /var/log/samba/log.smbd
sudo tail -f /var/log/samba/log.nmbd

# 查看客户端日志
sudo tail -f /var/log/samba/client.log

相关命令

命令 说明
smbstatus 显示当前Samba连接状态
testparm 测试Samba配置文件语法
nmblookup NetBIOS名称查询工具
mount.cifs 挂载CIFS/SMB文件系统
net Samba网络管理工具
rpcclient MS-RPC客户端工具
smbtree 以树形结构显示可用共享
smbtar 备份/恢复SMB共享

挂载SMB共享(mount.cifs)

除了使用smbclient,还可以直接挂载SMB共享到本地文件系统:

# 安装cifs-utils
sudo apt-get install cifs-utils

# 创建挂载点
sudo mkdir -p /mnt/windows_share

# 挂载共享
sudo mount -t cifs //192.168.1.100/Public /mnt/windows_share -o username=user,password=pass

# 使用凭据文件挂载
echo "username=user" > ~/.smbcreds
echo "password=pass" >> ~/.smbcreds
chmod 600 ~/.smbcreds
sudo mount -t cifs //server/share /mnt/windows_share -o credentials=~/.smbcreds

# 卸载共享
sudo umount /mnt/windows_share

SMB协议版本

协议 版本 说明
CIFS SMB1 传统协议,Windows NT/2000/XP
SMB2 2.0 Windows Vista/Server 2008
SMB2.1 2.1 Windows 7/Server 2008 R2
SMB3 3.0 Windows 8/Server 2012
SMB3.1.1 3.1.1 Windows 10/Server 2016+

指定SMB协议版本:

# 使用特定协议版本
smbclient //server/share -U user%pass -m SMB2
smbclient //server/share -U user%pass -m SMB3
smbclient //server/share -U user%pass -m NT1  # SMB1

# 配置默认协议版本(在smb.conf中)
# client min protocol = SMB2
# client max protocol = SMB3

安全注意事项

  1. 避免在命令行中直接使用密码,使用凭据文件或交互输入
  2. 确保凭据文件权限为600(仅所有者可读写)
  3. 禁用SMB1协议(CIFS)以提高安全性
  4. 使用加密传输(SMB3加密)
  5. 定期更换密码
  6. 使用防火墙限制SMB访问
  7. 监控Samba日志中的异常活动

实用脚本示例

脚本1:自动下载共享中的新文件

#!/bin/bash
# monitor_share.sh - 监控共享中的新文件

SERVER="192.168.1.100"
SHARE="Incoming"
USERNAME="monitor"
PASSWORD="monitor123"
LOCAL_DIR="/data/incoming"
STATE_FILE="/tmp/smbclient_last_check"
LOG_FILE="/var/log/monitor_share.log"

echo "$(date) 开始检查新文件" >> "$LOG_FILE"

# 获取远程文件列表
REMOTE_FILES=$(smbclient "//$SERVER/$SHARE" -U "$USERNAME%$PASSWORD" -c "ls" 2>/dev/null | \
    grep -E '^  [A-Za-z0-9]' | awk '{print $1}')

# 检查是否有新文件
if [ -f "$STATE_FILE" ]; then
    LAST_FILES=$(cat "$STATE_FILE")
    NEW_FILES=$(echo "$REMOTE_FILES" | grep -v -F "$LAST_FILES")
else
    NEW_FILES="$REMOTE_FILES"
fi

# 下载新文件
if [ -n "$NEW_FILES" ]; then
    echo "$(date) 发现新文件: $NEW_FILES" >> "$LOG_FILE"

    for FILE in $NEW_FILES; do
        smbclient "//$SERVER/$SHARE" -U "$USERNAME%$PASSWORD" -c "get $FILE" >> "$LOG_FILE" 2>&1
        if [ $? -eq 0 ]; then
            echo "$(date) 下载成功: $FILE" >> "$LOG_FILE"
        else
            echo "$(date) 下载失败: $FILE" >> "$LOG_FILE"
        fi
    done
else
    echo "$(date) 没有新文件" >> "$LOG_FILE"
fi

# 保存当前文件列表
echo "$REMOTE_FILES" > "$STATE_FILE"

脚本2:SMB共享健康检查

#!/bin/bash
# smb_health_check.sh - SMB共享健康检查

CONFIG_FILE="/etc/samba/smb_servers.conf"
LOG_FILE="/var/log/smb_health.log"
TIMEOUT=30

echo "=== SMB共享健康检查 $(date) ===" | tee -a "$LOG_FILE"

# 读取服务器列表
while IFS=, read -r SERVER SHARE USERNAME PASSWORD || [ -n "$SERVER" ]; do
    # 跳过注释和空行
    [[ "$SERVER" =~ ^# ]] && continue
    [[ -z "$SERVER" ]] && continue

    echo "检查: //$SERVER/$SHARE" | tee -a "$LOG_FILE"

    # 测试连接
    timeout $TIMEOUT smbclient "//$SERVER/$SHARE" -U "$USERNAME%$PASSWORD" -c "ls" >/dev/null 2>&1

    if [ $? -eq 0 ]; then
        echo "状态: 正常" | tee -a "$LOG_FILE"

        # 获取共享信息
        INFO=$(timeout $TIMEOUT smbclient "//$SERVER/$SHARE" -U "$USERNAME%$PASSWORD" -c "du" 2>/dev/null | head -1)
        echo "信息: $INFO" | tee -a "$LOG_FILE"
    else
        echo "状态: 失败" | tee -a "$LOG_FILE"
        echo "错误: 无法连接" | tee -a "$LOG_FILE"
    fi

    echo "---" | tee -a "$LOG_FILE"

done < "$CONFIG_FILE"

echo "检查完成" | tee -a "$LOG_FILE"

smbclient高级技巧

高级smbclient技巧:
  1. 脚本模式:使用-c选项执行脚本,结合bash实现自动化
  2. 递归操作:使用recurse命令启用目录递归操作
  3. 批量传输:使用mget/mput配合maskprompt
  4. tar备份:使用tar命令进行完整的共享备份/恢复
  5. 加密传输:使用-e选项启用SMB加密
  6. 协议协商:使用-m指定协议版本,解决兼容性问题
  7. 调试分析:使用-d 3进行详细调试,分析连接问题

smbclient命令速查表

用途 命令示例
列出共享 smbclient -L //server -U user%pass
连接共享 smbclient //server/share -U user%pass
匿名连接 smbclient //server/share -N
执行单命令 smbclient //server/share -U user%pass -c "ls"
下载文件 smbclient //server/share -U user%pass -c "get file.txt"
上传文件 smbclient //server/share -U user%pass -c "put local.txt"
批量下载 smbclient //server/share -U user%pass -c "mget *.pdf"
创建目录 smbclient //server/share -U user%pass -c "mkdir newdir"
删除文件 smbclient //server/share -U user%pass -c "rm file.txt"
发送消息 smbclient -M computername
使用凭据文件 smbclient //server/share -A ~/.smbcredentials
调试模式 smbclient //server/share -U user%pass -d 3