0%

搭建一个 WebDAV 服务器,可以选择不同的服务器软件,比如 Apache、Nginx 或其他开源解决方案。下面我将详细介绍如何在 Ubuntu 上使用 Apache HTTP Server 来搭建 WebDAV 服务器。

1. 安装 Apache 和 WebDAV 模块

首先,确保系统更新并安装 Apache HTTP Server 以及 WebDAV 所需的模块:

1
2
3
4
sudo apt update
sudo apt install apache2
sudo a2enmod dav
sudo a2enmod dav_fs

2. 配置 WebDAV 目录

接下来,配置一个目录来存储 WebDAV 文件,并在 Apache 中启用该目录的 WebDAV 功能。

编辑 Apache 的默认配置文件(例如 /etc/apache2/sites-available/000-default.conf),添加以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
Alias /webdav /var/www/webdav

<Directory /var/www/webdav>
DAV On
AuthType Basic
AuthName "WebDAV"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user

<LimitExcept GET OPTIONS>
Require valid-user
</LimitExcept>
</Directory>

3. 创建 WebDAV 目录并设置权限

创建用于存储 WebDAV 文件的目录,并设置适当的权限:

1
2
3
sudo mkdir /var/www/webdav
sudo chown -R www-data:www-data /var/www/webdav
sudo chmod -R 755 /var/www/webdav

4. 设置用户认证

为了保护 WebDAV 目录,需要设置基本的 HTTP 认证。创建一个认证文件并添加用户:

1
sudo htpasswd -c /etc/apache2/.htpasswd username

系统会提示输入并确认用户的密码。

5. 重启 Apache 服务器

完成上述配置后,重启 Apache 服务器以应用更改:

1
2
3
sudo systemctl restart apache2
sudo systemctl status apache2 # 查看是否正常运行

  1. 访问 WebDAV 服务器
    现在,WebDAV 服务器已经配置完成,可以通过以下 URL 访问:
1
http://your-server-ip/webdav

验证配置

你可以使用 Web 浏览器、命令行工具(如 curl)、或者 WebDAV 客户端(如 Cyberduck、WinSCP)来测试 WebDAV 服务器。

使用 curl 命令行工具测试:

1
2
3
4
5
# 上传文件
curl -u username:password -T localfile.txt http://your-server-ip/webdav/remote.txt

# 下载文件
curl -u username:password -O http://your-server-ip/webdav/remote.txt

示例客户端访问(Python)

使用 Python 中的 requests 库来访问 WebDAV 服务器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import requests
from requests.auth import HTTPBasicAuth

url = 'http://your-server-ip/webdav/test.txt'
username = 'your-username'
password = 'your-password'

# 上传文件
with open('localfile.txt', 'rb') as f:
response = requests.put(url, data=f, auth=HTTPBasicAuth(username, password))
print(response.status_code)

# 下载文件
response = requests.get(url, auth=HTTPBasicAuth(username, password))
with open('downloaded_test.txt', 'wb') as f:
f.write(response.content)
print(response.status_code)

结论

通过上述步骤,你已经成功在 Ubuntu 上使用 Apache HTTP Server 搭建了一个 WebDAV 服务器。WebDAV 服务器可以用于在线存储和管理文件,适用于协作编辑和文件同步。通过适当的认证和权限设置,可以确保数据的安全性。

其他操作

1、检查 Apache 错误日志

1
sudo tail -f /var/log/apache2/error.log

2、测试本地连接

1
2
curl -u username:password http://localhost/webdav/

3、检查 Apache 配置文件语法

1
2
sudo apache2ctl configtest

如果输出包含 Syntax OK,则表示配置文件语法正确。如果有错误,请根据提示修正。

4、检查监听端口

确保 Apache 正在监听端口 80:

1
2
sudo netstat -tuln | grep :80

输出中应该有一行类似以下内容:

1
2
tcp6       0      0 :::80                   :::*                    LISTEN

5、清理现有配置:

1
2
3
4
sudo a2dismod dav dav_fs
sudo rm /etc/apache2/.htpasswd
sudo rm -rf /var/www/webdav

6、修改 Apache 配置监听端口

首先,您需要确保 Apache 监听端口 8080。编辑 Apache 的主配置文件(通常是 ports.conf):

1
2
sudo vi /etc/apache2/ports.conf

添加以下行(如果已存在,确认其配置正确):

1
Listen 8080

配置虚拟主机以使用端口 8080

编辑默认的虚拟主机配置文件(通常是 000-default.conf):

1
sudo nano /etc/apache2/sites-available/000-default.conf

<VirtualHost *:80> 修改为 <VirtualHost *:8080>,并确保配置正确:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<VirtualHost *:8080>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html

Alias /webdav /var/www/webdav

<Directory /var/www/webdav>
DAV On
AuthType Basic
AuthName "WebDAV"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user

<LimitExcept GET OPTIONS>
Require valid-user
</LimitExcept>
</Directory>

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

7、You don’t have permission to access this resource.

访问 wevdav 服务器时,提示You don't have permission to access this resource.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<VirtualHost *:8080>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html

Alias /webdav /var/www/webdav

<Directory /var/www/webdav>
# 添加如下 3 行配置
Options Indexes FollowSymLinks
AllowOverride None
Require all granted

DAV On
AuthType Basic
AuthName "WebDAV"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user

<LimitExcept GET OPTIONS>
Require valid-user
</LimitExcept>
</Directory>

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

8、修改WebDAV 目录

如果您不想使用 /var/www/webdav 作为 WebDAV 目录,可以选择其他目录并进行相应的配置。以下是详细步骤,以 /data/webdav 为例:

首先,在您希望的位置创建新的 WebDAV 目录:

1
2
3
sudo mkdir -p /data/webdav
sudo chown -R www-data:www-data /data/webdav
sudo chmod -R 755 /data/webdav

修改/etc/apache2/sites-available/000-default.conf配置文件中的 WebDAV 目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

<VirtualHost *:8080>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html

Alias /webdav /data/webdav

<Directory /data/webdav>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted

DAV On
AuthType Basic
AuthName "WebDAV"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user

<LimitExcept GET OPTIONS>
Require valid-user
</LimitExcept>
</Directory>

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

9、确认目录权限和修改 Apache 用户

确保 WebDAV 目录 /data/webdav 具有适当的权限,使得 Apache 用户(通常是 www-data)有读写权限。

1
2
3
sudo chown -R www-data:www-data /data/webdav
sudo chmod -R 755 /data/webdav

确认 Apache 用户
确保 Apache 使用的用户和组是 www-data。这通常在 apache2.conf 或 envvars 文件中定义。

编辑 envvars 文件(Ubuntu/Debian 通常位于 /etc/apache2/envvars):

1
sudo vi /etc/apache2/envvars

确保以下行存在:

1
2
3
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data

如果不想用 用户和组是 www-data, 则创建新的用户和用户组,并修改上述配置

10、上传文件到 WebDAV 服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
from requests.auth import HTTPBasicAuth

# WebDAV 服务器的 URL 和目标路径
webdav_url = 'http://your-server-ip:8080/webdav/'
file_path = 'localfile.txt' # 本地文件路径
remote_path = webdav_url + 'remote_file.txt' # 远程文件路径

# WebDAV 用户名和密码
username = 'your_username'
password = 'your_password'

# 打开本地文件
with open(file_path, 'rb') as file:
# 使用 requests.put() 方法上传文件
response = requests.put(remote_path, data=file, auth=HTTPBasicAuth(username, password))

# 检查响应状态码
if response.status_code == 201 or response.status_code == 204:
print('文件上传成功')
else:
print(f'文件上传失败,状态码: {response.status_code}')
print(response.text)

11、上传文件夹到 WebDAV 服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import os
import requests
from requests.auth import HTTPBasicAuth

# WebDAV 服务器的 URL 和目标路径
webdav_url = 'http://your-server-ip:8080/webdav/'
local_folder = 'local_folder/' # 本地文件夹路径

# WebDAV 用户名和密码
username = 'your_username'
password = 'your_password'

# 上传单个文件
def upload_file(local_file, remote_file):
with open(local_file, 'rb') as file:
response = requests.put(remote_file, data=file, auth=HTTPBasicAuth(username, password))
return response.status_code

# 递归上传文件夹中的所有文件
def upload_folder(local_folder, remote_folder):
for root, _, files in os.walk(local_folder):
for file in files:
local_file = os.path.join(root, file)
relative_path = os.path.relpath(local_file, local_folder)
remote_file = os.path.join(remote_folder, relative_path).replace("\\", "/")
response_code = upload_file(local_file, remote_file)
if response_code in [201, 204]:
print(f'文件上传成功: {local_file}')
else:
print(f'文件上传失败: {local_file},状态码: {response_code}')

# 上传文件夹
upload_folder(local_folder, webdav_url)


一、json序列化时默认支持的数据类型

Python JSON
dict object
list, tuple array
str string
int, float, int- & float-derived Enums number
True true
False false
None null
除此之外的数据类型,就需要我们个性化定制。

二、定制支持datetime类型

官方文档中关于json.dumps方法的一个参数(cls)说明:

To use a custom JSONEncoder subclass (e.g. one that overrides the default() method to serialize additional types), specify it with the cls kwarg; otherwise JSONEncoder is used.

官方文档中的一个Demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import json
>>> class ComplexEncoder(json.JSONEncoder):
... def default(self, obj):
... if isinstance(obj, complex):
... return [obj.real, obj.imag]
... return json.JSONEncoder.default(self, obj)
...
>>> dumps(2 + 1j, cls=ComplexEncoder)
'[2.0, 1.0]'
>>> ComplexEncoder().encode(2 + 1j)
'[2.0, 1.0]'
>>> list(ComplexEncoder().iterencode(2 + 1j))
['[', '2.0', ', ', '1.0', ']']

定制支持datetime类型需要完成以下步骤:

  • 定义一个继承自JSONEncoder的类,重写里面的default方法,定义对datetime类型数据的处理方法
  • 在用dumps函数序列化时,参数cls的值就设为我们上面写的这个子类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

import json
from datetime import datetime


time = datetime(1987,2,5)

class DatetimeJsonEncoder(json.JSONEncoder):
'''这是JSONEncoder的子类'''
def default(self,obj): # pylint: disable = method-hidden
'''这是重写的default方法
:参数 obj: 需要序列化的对象
'''
# 如果是datetime对象,就按照我们自定义的格式转化为列表
if isinstance(obj, datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(obj, date):
return obj.strftime('%Y-%m-%d')
else:
# 其他的基本类型数据,就按照JSONEncoder自己的方法处理
return json.JSONEncoder.default(self,obj)

string = json.dumps({'name':'Alex Brightman','birthday':time},cls=DatetimeJsonEncoder)

Python

面试题

django flask tornado 底层实现原理,三者使用场景

gunicore 实现原理

单例作用及应用场景,wraps修饰器的作用

py3 和 py2有哪些区别,pep8 风格

类方法,静态方法,实例方法 区别及应用场景

深拷贝浅拷贝

新式类和旧式类的区别

python 常用的设计模式

dict为什么无序,python3的 dict 是有序的

装饰器传参

Golang

面试题

make 和 new 的区别

Mysql

面试题

索引分类、失效、如何优化

ACID的具体实现,隔离级别、mvcc 实现及作用,锁

数据落盘,mysql 优化,

redo log,binlog,undo log、buffer pool

Redis

面试题

分布式锁

数据类型,应用场景,底层结构

持久化(aof、rdb、aof 和 rdb 混合使用)

mysql 和 redis 事务的区别,redis 原子性和 pipline 的区别

redis 多线程

Kafka

面试题

kafka 如何保证不丢失不重复消费数据

kafka 主副本挂掉后会不会丢失数据

kafka 副本同步时主副本挂掉 同步了一个副本 其他副本会不会和已同步的副本数据不一致

算法

ES

面试题

倒排索引

如何调优 es

Flink

K8S,Docker

面试题

k8s 的 pod 的创建流程

k8s 网络请求流程

k8s切换 pod 会不会导致流量丢失

docker命令

Vue

Git

HTTP

面试题

服务器状态码

什么是 http 协议,http 常用的字段

Linux

设计题

敏捷开发

其他


题目一:公司有n个组,每组人数相同,>=1人,需要进行随机的组队吃饭。

要求:

  1. 两两一队,不能落单,落单则三人一队

  2. 一个人只出现一次

  3. 队伍中至少包含两个组

  4. 随机组队,重复执行程序得到的结果不一样

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GroupList = [  # 小组列表

['小名', '小红', '小马', '小丽', '小强'],

['大壮', '大力', '大1', '大2', '大3'],

['阿花', '阿朵', '阿蓝', '阿紫', '阿红'],

['A', 'B', 'C', 'D', 'E'],

['一', '二', '三', '四', '五'],

['建国', '建军', '建民', '建超', '建跃'],

['爱民', '爱军', '爱国', '爱辉', '爱月']
]

输入:GroupList
输出:(A, 小名),(B, 小红)。。。
阅读全文 »

需求:

同一域名+不同后缀转发到不同服务器ip+端口的webapi接口(198.122.133.4:800,199.122.133.5:800,197.122.133.6:800)

说明:

nginx location proxy_pass 后面的url 加与不加/的区别

在nginx中配置proxy_pass时,当在后面的url加上了/,相当于是绝对根路径,则nginx不会把location中匹配的路径部分代理走;

如果没有/,则会把匹配的路径部分也给代理走。

阅读全文 »

clone 所有分支到本地

1
2
3
4
git clone xxxx.git
git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done
git fetch --all
git pull --all

push 到新的远程空仓库

1
2
3
4
5
git remote rename origin old-origin
git remote add origin https://yyyy.git
git push -u origin --all
git push -u origin --tags

原文链接:https://blog.csdn.net/weixin_41012767/article/details/121920518

问题描述

当您使用两个ECS实例挂载同一个NFS文件系统,在ECS A实例上追加写文件,在ECS B实例上使用tail -f命令查看文件内容的变化时,在ECS A实例上写完之后,在ECS B实例上查看文件内容变化会有10~30秒的延时。然而相同的场景下,如果直接在ECS B实例上写文件(比如vi)可以立即看到更新的内容。

问题原因

该现象与mount的选项和tail -f命令的实现相关:

  • 挂载使用的mount命令为:mount -t nfs4 /mnt/,对于在ECS B实例上以这一方式挂载的NFS文件系统,默认情况下Kernel对文件和目录的属性维护了一份metadata缓存,文件和目录属性(包括许可权、大小、和时间戳)缓存的目的是减少NFSPROC_GETATTR远程过程调用(RPC)的需求。

  • tail -f命令的实现是通过sleep和fstat观察文件属性(主要是文件大小)的变化,然后读入文件并输出。可见,tail -f命令是否能实时输出文件内容主要取决于fstat的结果,由于metadata cache的存在,fstat轮询到的并不是实时的文件属性。因此,即使在NFS服务器端文件已经更新,但使用tail -f命令却无法知道文件已经改动,于是输出就会出现延时。

解决方法

使用mount的noac选项可以关闭文件和目录属性的缓存。

1
2
3
mount -t nfs4 -o noac /mnt/

sudo mount -t nfs -o noac,vers=3,nolock,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport xxxxxx.cn-beijing.nas.aliyuncs.com:/app/work_log /worker_log

适用于

文件存储NAS

pip uninstall package 后,如果再次安装 package 时, 发现不是新下载的 package, 而是使用的 cache,

1
2
3
4
[root@unity-004 blender-3d]# pip install -r requirements.txt -i https://pypi.xxxx.com/simple
Looking in indexes: https://pypi.xxxx.com/simple
Collecting pytoshop==1.2.9
Using cached pytoshop-1.2.9-py2.py3-none-any.whl

如果要不想用 cache 去安装,则是由如下参数–no-cache-dir

1
2
pip install -r requirements_local.txt  --no-cache-dir

指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Make a fresh clone of YOUR_REPO
git clone YOUR_REPO
cd YOUR_REPO

# Create tracking branches of all branches
for remote in `git branch -r | grep -v /HEAD`; do git checkout --track $remote ; done

# Remove DIRECTORY_NAME from all commits, then remove the refs to the old commits
# (repeat these two commands for as many directories that you want to remove)
git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch DIRECTORY_NAME/' --prune-empty --tag-name-filter cat -- --all
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d

# Ensure all old refs are fully removed
rm -Rf .git/logs .git/refs/original

# Perform a garbage collection to remove commits with no refs
git gc --prune=all --aggressive

# Force push all branches to overwrite their history
# (use with caution!)
git push origin --all --force
git push origin --tags --force

git push origin 报错

1
error: failed to push some refs to 'ssh://code.xxx.com:10579/xxx/xxxx.git'

如果有如上报错 则需要在 GitLab 项目中的 Settings--Repository--Protected Branches 将保护分支unprotect

参考文档

Remove folder and its contents from git/GitHub’s history

Case 1. 从 0 开始配置使用 git-lfs

我们要指定 git-lfs 会把哪些文件当作大文件,指定方式比如有:

指定文件后缀名

git lfs track “.filetype”
指定某个目录下的所有文件
git lfs track “directory/

具体指定某个文件
git lfs track “path/to/file”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> mkdir <repo>
> cd <repo>
> git init
> git lfs track "*.filetype" # 比如 *.zip

# 其实 git lfs track 会修改 .gitattributes 文件的内容,可以做一个快速的验证
# > cat .gitattributes
# *.zip filter=lfs diff=lfs merge=lfs -text

# 下面假定在 Github 有一个远程仓库供我们使用
# 往仓库里加你先前指定的文件类型的大文件
> git add .
> git commit -m ""
> git branch -M main
> git remote add origin git@github.com:<username>/<remote_repo_name>.git # 这里替换为自己的用户名和远程仓库名
> git push -u origin main
# 此时命令行会显示
# > uploading LFS objects
# 如果没有采用 git-lfs,则显示如下内容
# > Enumerating objects: 3, done.
# Counting objects: 100% (3/3), done.
# Delta compression using up to 8 threads
# Compressing objects: 100% (2/2), done.

Case 2. 要在已有的仓库上用 git-lfs 追踪某些文件

此时只是简单的使用 git lfs track “” 是没用的,因为你之前的 commit 已经生成了快照,你无法追踪历史中的这些大文件。

git-lfs 只会在你开始设置的此刻之后追踪新生成的指定文件

可以快速做个验证,假设我们还在这个仓库里⬇️

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> ls > test1.txt
> ls -l > test2.txt
> git add test1.txt test2.txt
> git commit -m "Add txt files"

# 假设我们现在要把 txt 文件当成是大文件,我们可能会想这么做
> git lfs track "*.txt"
> git add .gitattributes
> git commit -m "Track *.txt files"
> git lfs ls-files # 此时你会发现 git-lfs 并没有追踪 txt 文件

> echo "hello" > test3.txt
> git add test3.txt
> git commit -m "Add test3.txt"
> git lfs ls-files # 此时你可以在输出中看到 test3.txt

正确的方法是使用 git lfs migrate,这里只列举了简单的用法,更复杂的可以看看手册。比如可以用 –include-ref= 指定分支,多个分支的时候最好一个分支一个分支地迁移,最后是 git push –all -f

1
2
3
4
5
6
> git lfs migrate import --include="*.txt"  # 在当前分支上执行
> git lfs ls-files # 此时可以发现 text1.txt 和 text2.txt 也被追踪到了
> git push --force # 让远程仓库也改过来
Case 3. 不再跟踪某些文件
> git lfs untrack "*.filetype"
> git rm --cached "*.txt"

其他常用命令

查看当前 git-lfs 正在追踪的文件类型

git lfs track
查看当前 git-lfs 正在追踪哪些文件
git lfs ls-file

参考文档

详解 Git 大文件存储(Git LFS)
Jenkins 中的 Git-LFS 设置
git-lfs 指南
git-lfs-migrate(1) - Migrate history to or from Git LFS