介绍

首先: 绝对好用! 绝对好用! 绝对好用!

之所以寻找可通过命令行来共享文件是因为近半年的工作常常常需要不停的从服务器内拷贝程序的配置文件,为此无法忍受各种客户环境的刁难。开始寻找解决痛苦的方法:(离职?、技术实现?)

通过该工具,可实现仅通过命令行执行 curl xxx.com/scripts/init.sh | bash -s 文件名 即可从服务器内中转各种文件,返回文件链接,并下载到本地。(最终效果可直接看文章末尾)

目前我已很依赖这个工具,遇到从服务器内拷贝文件时,一天不使用,浑身难受,坐立不安。恨不得立马下班。😂😂😂

原理

本文章核心围绕transfer.sh展开额外的扩展。

transfer.sh工具是一个外国开源的命令行共享文件工具,提供免费的在线服务以及自建的方法。

然而我们本次通过私有化部署中转服务 transfer.sh 将文件暂存至你的服务器内并返回文件的链接,通过本地 wget 等工具下载至本地。下载本地后也可实现自动销毁服务器上的文件。

为何要私有化部署:

一是因为涉及文件传输,保不齐会上传一些安全性要求很高的文件
二是transfer.sh工具主要国外平台,国内访问网络质量可能略差,再者可能会因为国内某特色主义导致无法访问平台

据以上两点,私有化部署最为优选。(当然你只是想玩玩。体验一把的话,直接用人家的服务也不错。)

环境准备

一只域名
一只域名的SSL证书(为了保证文件传输的安全)
一只已部署Docker的Linux、内存 >256MB 足以。

部署服务

创建所需目录

mkdir -p /app/transfer/{data,ssl,openresty/{www/scripts,conf,logs}}

证书准备

这里需要先申请好域名的ssl证书,申请步骤大家可自行百度。

申请好证书后,下载 nginx 格式的证书,将xxx.pemxxx.key 放置在 /app/transfer/ssl 路径下,并重命名为: ssl.key ssl.key

完整的文件路径如下

/app/transfer/ssl/ssl.key
/app/transfer/ssl/ssl.pem

启动共享服务

准备文件共享服务启动脚本:/app/transfer/startup_transfer.sh 并执行

export transfer_domain='transfer.itan90.cn'  # 这里写你的域名
export transfer_email='transfer@init.ac'   # 这里写你的邮箱
docker rm -f transfer
docker run -itd --name=transfer \
--restart=always \
-p 8080:8080 \
-v /app/transfer/ssl/:/ssl/ \
-v /app/transfer/data/:/data/ \
-e EMAIL_CONTACT=${transfer_email} \
registry.cn-hangzhou.aliyuncs.com/bohai_repo/transfer.sh:v1.6.1 \
--provider local \
--basedir /data/ \
--tls-listener :443 \
--tls-cert-file /ssl/ssl.pem \
--tls-private-key /ssl/ssl.key \
--lets-encrypt-hosts ${transfer_domain}

此时访问 http://你的主机IP:8080 即可打开部署的transfer服务。这里我们先不管,继续往后。

启动代理服务

准备反向代理配置:/app/transfer/openresty/conf/transfer.conf

server {
    listen 80;
    listen 443 ssl;
    # 这里改成你的域名
    server_name transfer.itan90.cn;
    # 最大上传文件大小
    client_max_body_size 4096m;

    # ssl配置
    ssl_certificate     /etc/nginx/ssl/ssl.pem;
    ssl_certificate_key /etc/nginx/ssl/ssl.key;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # 强制跳转到HTTPS
    if ($server_port !~ 443){
        rewrite ^(/.*)$ https://$host$1 permanent;
    }

    # 代理后端服务
    location / {
        proxy_pass https://transfer:443;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 提供静态资源
    location /scripts/ {
        root   /etc/nginx/www/;
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
    }

   access_log  /etc/nginx/logs/transfer.access.log;
   error_log   /etc/nginx/logs/transfer.error.log;
}

准备openresty服务启动脚本:/app/transfer/startup_openresty.sh 并执行

docker rm -f openresty
docker run -itd --name=openresty \
-p 80:80 \
-p 443:443 \
--link transfer:transfer \
-v /app/transfer/ssl/:/etc/nginx/ssl \
-v /app/transfer/openresty/logs/:/etc/nginx/logs \
-v /app/transfer/openresty/conf/:/etc/nginx/conf.d \
-v /app/transfer/openresty/www/:/etc/nginx/www \
registry.cn-hangzhou.aliyuncs.com/bohai_repo/openresty:1.21.4

测试访问

1、将域名解析至你的服务器
2、访问https://域名 是否可打开transfer服务页面

如果测试通过,继续往下

编写处理脚本

准备客户端上传文件脚本:/app/transfer/openresty/www/scripts/file.sh

#!/usr/bin/env bash

SECONDS=0
file_name=$1
transfer_file='https://这里改成你的域名'

trap 'rm -f "$TEMP_FILE"' EXIT;readonly TEMP_FILE=$(mktemp) || exit 1

if [[ $file_name == '' ]];then
  echo "[ERROR] 使用方式: curl -s ${transfer_file}/scripts/file.sh|bash -s {file_name}";exit 1
else
  base_file_name=$(basename $file_name)
fi

if [[ ! -f $file_name ]];then
  echo "[ERROR] 文件: ${file_name} 未找到";exit 1
fi

if [[ $save_file_control == '' ]];then
  echo "[WARN] 未定义文件交换策略,将使用默认值:仅可下载一次,有效期一天."
  echo "[INFO] 您可以在执行脚本之前执行此操作;打开文件交换策略控制:"
  echo ""
  echo "$ export save_file_control=true"
  echo "$ export max_save_days=3"
  echo "$ export max_download_nums=10"
  echo ""
  echo "[INFO] 或者,完全禁用文件交换策略:"
  echo ""
  echo "$ export save_file_control=false"
  echo ""
  echo "[INFO] 文件上传任务已开始..."
  echo ""
  curl -s -w '\n' -H "Max-Days: 1" -H "Max-Downloads: 1" --upload-file $file_name ${transfer_file}/$base_file_name > $TEMP_FILE
elif [[ $save_file_control == 'false' ]];then
  curl -s -w '\n' --upload-file $file_name ${transfer_file}/$base_file_name > $TEMP_FILE
else
  if [[ $max_save_days == '' ]];then echo "undefined max_save_days";exit 1;fi
  if [[ $max_download_nums == '' ]];then echo "undefined max_download_nums";exit 1;fi
  curl -s -w '\n' -H "Max-Days: $max_save_days" -H "Max-Downloads: $max_download_nums" --upload-file $file_name ${transfer_file}/$base_file_name > $TEMP_FILE
fi


if [[ $? == 0 ]];then
  transfer_result=$(cat $TEMP_FILE)
  if [[ $(cat $TEMP_FILE|grep 413) != '' ]];then 
    # 文件大小超出openresty配置的client_max_body_size值则抛出异常
    echo "[ERROR] 上传的文件过大"
  else
    echo "[INFO] $file_name 上传成功; 总耗时:$SECONDS秒,文件地址: $transfer_result"
  fi
fi

之后测试访问 http://你的域名/scripts/file.sh 看是否可正常获取上述的脚本,如果可以,则步骤已成功100%

最终效果

直接食用

https://transfer.init.ac 是我已经搭建好的平台,可以直接使用。最终替换为自己的域名即可。

# 本地文件路径
$ cat /etc/centos-release
CentOS Linux release 7.9.2009 (Core)

# 开始传输文件并返回文件链接
$ curl -4s https://transfer.init.ac/scripts/file.sh|bash -s /etc/centos-release
/etc/centos-release transfer success; file url: https://transfer.init.ac/vC3mF3/centos-release

# 第一次测试请求访问文件
$ curl https://transfer.init.ac/vC3mF3/centos-release
CentOS Linux release 7.9.2009 (Core)

# 第二次测试请求访问文件
$ curl https://transfer.init.ac/vC3mF3/centos-release
Not Found

细心的同学肯定要问,为什么返回的文件地址只能请求/下载一次呢? 是因为我觉得这是为了你的数据安全着想

哼

想自定义?那接着往下吧~

自定义文件共享控制

可实现文件最大可保留天数、文件最大可下载次数

开启控制

export save_file_control=true
# 文件最大保存天数
export max_save_days=3
# 文件最大下载次数
export max_download_nums=2

取消控制

unset save_file_control

不限制文件上传策略

export save_file_control=false

参考帮助

最后修改:2024 年 01 月 08 日
如果觉得我的文章对你有用,请随意赞赏