使用Samba(SMB/CIFS)

  • 安装mount_smbfs

你需要安装mount_smbfs包来支持SMB/CIFS协议。

使用MAC的brew包管理器安装:

brew install mount_smbfs
  • 创建挂载点

选择一个本地目录作为挂载点,如果不存在,则创建它:

mkdir /mnt/smbshare

/mnt/smbshare修改为自定义挂载点。

创建挂载脚本

  • 首先创建脚本文件

sudo vi ~/smb-mount
  • 将以下代码复制到文件中

#!/bin/bash

# SMB多挂载点管理脚本
# 支持挂载、卸载、状态查看功能

VERSION="1.2.0"
CONFIG_FILE="$HOME/.smb_mounts.conf"
LOG_FILE="$HOME/smb_mount.log"

# 默认配置数组
# 格式: "IP地址,共享名称,挂载点路径,用户名,密码"
DEFAULT_CONFIG=(
    "example.com,/sharename,/mnt/smbshare,user,password"
)

# 初始化配置文件
init_config() {
    if [[ ! -f "$CONFIG_FILE" ]]; then
        echo "# SMB挂载配置" > "$CONFIG_FILE"
        echo "# 格式: IP地址/域名,共享名称,挂载点路径,用户名,密码" >> "$CONFIG_FILE"
        echo "# 每行一个配置项" >> "$CONFIG_FILE"
        echo "# 注意: 密码以明文存储,请确保文件安全" >> "$CONFIG_FILE"
        echo "" >> "$CONFIG_FILE"
        for config in "${DEFAULT_CONFIG[@]}"; do
            echo "$config" >> "$CONFIG_FILE"
        done
        echo "已创建默认配置文件: $CONFIG_FILE"
        echo "请检查配置后重新运行脚本"
        exit 0
    fi
}

# 显示帮助信息
show_help() {
    cat << EOF
SMB多挂载点管理脚本 v$VERSION

用法: $0 [命令] [选项]

命令:
  mount      挂载所有配置的SMB共享
  unmount    卸载所有SMB共享(使用强力卸载)
  status     查看当前挂载状态
  list       列出所有配置项
  log        查看日志文件

选项:
  -h, --help     显示此帮助信息
  -v, --version  显示版本信息
  -f, --force    强制操作(挂载时重新创建目录)

配置文件: $CONFIG_FILE
日志文件: $LOG_FILE

配置格式:
  IP地址/域名,共享名称,挂载点路径,用户名,密码

示例:
  example.com,/sharename,/mnt/smbshare,user,password

注意:
  1. 首次运行会自动创建配置文件
  2. 建议手动创建挂载点目录并设置适当权限
  3. 密码以明文存储,请确保配置文件安全 (chmod 600 $CONFIG_FILE)
  4. 卸载命令使用sudo权限,需要输入密码
EOF
}

# 显示版本信息
show_version() {
    echo "SMB多挂载点管理脚本 v$VERSION"
}

# 记录日志
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# 读取配置文件
read_config() {
    local configs=()
    while IFS= read -r line; do
        # 跳过注释行和空行
        if [[ "$line" =~ ^# ]] || [[ -z "$line" ]]; then
            continue
        fi
        configs+=("$line")
    done < "$CONFIG_FILE"
    echo "${configs[@]}"
}

# 检查并创建挂载点目录
ensure_mount_point() {
    local mount_point="$1"
    local force="$2"
    
    if [[ "$force" == "true" && -d "$mount_point" ]]; then
        log "强制模式: 删除并重新创建目录 $mount_point"
        sudo rm -rf "$mount_point" 2>/dev/null
    fi
    
    if [[ ! -d "$mount_point" ]]; then
        log "创建挂载点目录: $mount_point"
        mkdir -p "$mount_point"
        if [[ $? -ne 0 ]]; then
            log "错误:无法创建挂载点目录 $mount_point"
            return 1
        fi
        # 设置合适的权限
        chmod 755 "$mount_point"
    else
        # 检查目录是否为空(如果不是挂载点)
        if ! mount | grep -q "$mount_point" && [[ "$(ls -A "$mount_point" 2>/dev/null)" ]]; then
            log "警告:挂载点目录 $mount_point 不为空,可能影响挂载"
            return 1
        fi
    fi
    return 0
}

# 检查服务器可达性
check_server() {
    local server="$1"
    log "检查服务器可达性: $server"
    
    # 尝试ping(对于域名可能失败,但不影响后续操作)
    if ping -c 1 -t 3 "$server" &> /dev/null; then
        log "服务器 $server 可达"
        return 0
    else
        log "警告:无法ping通服务器 $server,继续尝试连接..."
        return 1
    fi
}

# 卸载SMB共享 - 使用强力卸载命令
unmount_share() {
    local mount_point="$1"
    local force="$2"
    
    log "检查挂载点: $mount_point"
    if mount | grep -q "$mount_point"; then
        log "发现挂载: $mount_point"
        return 0
    else
        log "未挂载: $mount_point"
        return 1
    fi
}

# 强力卸载所有SMB共享
unmount_all_smb() {
    log "开始强力卸载所有SMB共享"
    echo "正在卸载所有SMB共享,需要sudo权限..."
    
    # 显示当前挂载的SMB共享
    local smb_mounts=$(mount -t smbfs 2>/dev/null | wc -l)
    if [[ $smb_mounts -gt 0 ]]; then
        echo "当前挂载的SMB共享:"
        mount -t smbfs
        echo ""
    fi
    
    # 使用强力命令卸载所有SMB共享
    log "执行: sudo umount -Af -t smbfs"
    sudo umount -Af -t smbfs 2>> "$LOG_FILE"
    local result=$?
    
    # 等待一下让卸载完成
    sleep 2
    
    # 检查是否还有SMB挂载
    local remaining_mounts=$(mount -t smbfs 2>/dev/null | wc -l)
    
    if [[ $remaining_mounts -eq 0 ]]; then
        log "成功卸载所有SMB共享"
        echo "✓ 所有SMB共享已成功卸载"
        return 0
    else
        log "警告:仍有SMB挂载存在,数量: $remaining_mounts"
        echo "⚠️  仍有SMB挂载存在,尝试其他方法..."
        
        # 尝试使用diskutil卸载
        for mount_point in $(mount -t smbfs | awk '{print $3}'); do
            log "尝试diskutil卸载: $mount_point"
            diskutil unmount force "$mount_point" 2>> "$LOG_FILE"
        done
        
        # 再次检查
        sleep 2
        remaining_mounts=$(mount -t smbfs 2>/dev/null | wc -l)
        
        if [[ $remaining_mounts -eq 0 ]]; then
            log "通过diskutil成功卸载剩余挂载"
            echo "✓ 所有SMB共享已成功卸载"
            return 0
        else
            log "错误:无法完全卸载所有SMB共享,剩余: $remaining_mounts"
            echo "❌ 无法完全卸载所有SMB共享"
            return 1
        fi
    fi
}

# 挂载SMB共享
mount_share() {
    local server="$1"
    local share="$2"
    local mount_point="$3"
    local user="$4"
    local pass="$5"
    local force="$6"
    
    # 确保挂载点存在且为空
    if ! ensure_mount_point "$mount_point" "$force"; then
        return 1
    fi
    
    local smb_url="smb://${user}:${pass}@${server}/${share}"
    log "尝试挂载: $smb_url 到 $mount_point"
    
    # 方法1: 使用mount_smbfs(最可靠)
    log "尝试使用mount_smbfs挂载..."
    /sbin/mount -t smbfs "//${user}:${pass}@${server}/${share}" "$mount_point" 2>> "$LOG_FILE"
    
    if [[ $? -eq 0 ]]; then
        log "mount_smbfs挂载成功: $mount_point"
        return 0
    fi
    
    # 方法2: 使用AppleScript(需要GUI环境)
    log "mount_smbfs失败,尝试AppleScript方式..."
    osascript << EOF 2>/dev/null
try
    mount volume "smb://${user}:${pass}@${server}/${share}"
    return true
on error
    return false
end try
EOF
    
    # 等待并检查是否挂载成功
    sleep 3
    if mount | grep -q "$mount_point"; then
        log "AppleScript挂载成功: $mount_point"
        return 0
    fi
    
    # 方法3: 使用open命令(macOS推荐)
    log "AppleScript失败,尝试open命令..."
    open "smb://${user}:${pass}@${server}/${share}" 2>> "$LOG_FILE"
    sleep 3
    
    if mount | grep -q "$mount_point"; then
        log "open命令挂载成功: $mount_point"
        return 0
    fi
    
    log "错误:所有挂载方法都失败: $share 到 $mount_point"
    return 1
}

# 查看挂载状态
check_status() {
    local configs=($(read_config))
    local mounted=0
    local total=0
    
    echo "当前SMB挂载状态:"
    echo "========================"
    
    for config in "${configs[@]}"; do
        IFS=',' read -r server share mount_point user pass <<< "$config"
        ((total++))
        
        if mount | grep -q "$mount_point"; then
            echo "[✓] $mount_point (//$server/$share)"
            ((mounted++))
        else
            echo "[ ] $mount_point (//$server/$share)"
        fi
    done
    
    echo "========================"
    echo "配置挂载: $mounted/$total"
    
    # 显示所有SMB挂载
    echo ""
    echo "系统当前所有SMB挂载:"
    echo "========================"
    mount -t smbfs 2>/dev/null || echo "无SMB挂载"
    
    # 显示挂载数量统计
    local all_smb_mounts=$(mount -t smbfs 2>/dev/null | wc -l)
    echo "总计SMB挂载: $all_smb_mounts"
    
    if [[ $mounted -eq $total ]]; then
        return 0
    elif [[ $mounted -eq 0 ]]; then
        return 2
    else
        return 1
    fi
}

# 列出所有配置
list_config() {
    local configs=($(read_config))
    local i=1
    
    echo "SMB挂载配置:"
    echo "========================"
    
    for config in "${configs[@]}"; do
        IFS=',' read -r server share mount_point user pass <<< "$config"
        # 隐藏密码
        hidden_pass="${pass:0:1}****${pass: -1}"
        echo "$i. //$server/$share"
        echo "   挂载点: $mount_point"
        echo "   用户名: $user"
        echo "   密码: $hidden_pass"
        echo ""
        ((i++))
    done
}

# 查看日志
show_log() {
    if [[ -f "$LOG_FILE" ]]; then
        echo "日志文件内容: $LOG_FILE"
        echo "========================"
        tail -20 "$LOG_FILE"
    else
        echo "日志文件不存在: $LOG_FILE"
    fi
}

# 执行挂载操作
do_mount() {
    local force="$1"
    local configs=($(read_config))
    local success=0
    local total=0
    
    log "开始挂载SMB共享"
    
    # 先卸载所有现有的SMB挂载(避免冲突)
    echo "为确保干净状态,先卸载现有SMB挂载..."
    unmount_all_smb
    
    for config in "${configs[@]}"; do
        IFS=',' read -r server share mount_point user pass <<< "$config"
        ((total++))
        
        log "处理: //$server/$share → $mount_point"
        
        # 检查服务器可达性(不强制要求,仅记录)
        check_server "$server"
        
        # 执行挂载
        if mount_share "$server" "$share" "$mount_point" "$user" "$pass" "$force"; then
            ((success++))
        fi
    done
    
    log "挂载完成: 成功 $success/$total"
    echo "挂载完成: 成功 $success/$total"
    
    if [[ $success -eq $total ]]; then
        return 0
    else
        return 1
    fi
}

# 执行卸载操作
do_unmount() {
    log "开始卸载所有SMB共享"
    unmount_all_smb
}

# 主程序
main() {
    # 初始化配置文件
    init_config
    
    local force="false"
    local command="$1"
    
    # 检查强制参数
    if [[ "$2" == "-f" || "$2" == "--force" ]]; then
        force="true"
    fi
    
    # 解析参数
    case "$command" in
        mount|m)
            do_mount "$force"
            ;;
        unmount|u)
            do_unmount
            ;;
        status|s)
            check_status
            ;;
        list|l)
            list_config
            ;;
        log)
            show_log
            ;;
        -h|--help|help|"")
            show_help
            ;;
        -v|--version|version)
            show_version
            ;;
        *)
            echo "错误: 未知命令 '$command'"
            echo "使用 '$0 --help' 查看帮助"
            exit 1
            ;;
    esac
}

# 启动主程序
main "$@"
  • 保存文件后,设置执行权限

sudo chmod +x ~/smb-mount
  • 第一次运行时,输入此命令,生成配置文件
.~/smb-mount
  • 第一次运行时,输入此命令,生成配置文件,并进行编辑。
# SMB挂载配置
# 格式: IP地址,共享名称,挂载点路径,用户名,密码
# 每行一个配置项
example.com,/sharename,/mnt/smbshare,user,password

使用方法

现在你可以使用这个脚本方便地管理SMB挂载:

🔹 挂载所有共享

.~/smb-mount mount

🔹 卸载所有共享

.~/smb-mount unmount

🔹 查看挂载状态

.~/smb-mount status

🔹 查看挂载列表

.~/smb-mount list

 🔹 显示运行日志

.~/smb-mount log

如果需要开机自动挂载

🔹方法

  • 使用苹果自带的自动操作工具,选择脚本文件smb-mount,文稿类型选择应用程序,打开后在左侧选择运行shell脚本,并拖拽到右侧,命令为:

.~/smb-mount mount

存储为应用程序,并在设置→通用→登录项,添加此App,就可以开机自动挂载了。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐