BNU-FZH

fengzhenhua@outlook.com

若文章中几处需要添加相同内容的脚注,各自都写\footnote{*}的话,则会出现好几个内容重复的脚注。这个问题可以通过“标签引用”+“上标”来解决。比如我们要给ORLJaffe都添加同样的脚注,可以这样:

1
2
ORL\footnote{http://blog.csdn.net/bear\_kai\label{web}} and
Jaffe\textsuperscript{\ref {web}}.

注意网址中有下划线时,在latex中需要额外加一个反斜杠即“转义字符”。

其他参考:LaTeX 技巧 950:LaTeX 攻略之脚注常用技巧

默认情况下 pip 使用的是国外的镜像,在下载的时候速度非常慢,本文我们介绍使用国内清华大学的源,地址为:

清华地址
1
https://pypi.tuna.tsinghua.edu.cn/simple

我们可以直接在 pip 命令中使用 -i 参数来指定镜像地址,例如:

1
pip3 install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple

以上命令使用清华镜像源安装 numpy 包。这种只对当前安装对命令有用,如果需要全局修改,则需要修改配置文件。

Linux/Mac os 环境中,配置文件位置在 ~/.pip/pip.conf(如果不存在创建该目录和文件):

1
mkdir ~/.pip

打开配置文件 ~/.pip/pip.conf,修改如下:

1
2
3
4
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host = https://pypi.tuna.tsinghua.edu.cn

查看 镜像地址:

1
2
3
$ pip3 config list   
global.index-url='https://pypi.tuna.tsinghua.edu.cn/simple'
install.trusted-host='https://pypi.tuna.tsinghua.edu.cn'

可以看到已经成功修改了镜像。

Windows下,你需要在当前对用户目录下(C:\\Users\\xx\\pip,xx 表示当前使用对用户,比如张三)创建一个 pip.ini在pip.ini文件中输入以下内容:

1
2
3
4
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host = pypi.tuna.tsinghua.edu.cn

其他国内镜像源

trash-cli 用于移动文件到回收站,同时会记录文件的原地址、删除日期和权限。trash-cli 和 KDE、GNOME、XFCE 使用同一个回收站,你可以在命令行或脚本运行 trash-cli。

安装

archlinux
1
sudo pacman -S trash-cli

命令

命令 作用
trash-put 把文件或目录移动到回收站
trash-empty 清空回收站
trash-list 列出回收站文件
trash-restore 恢复回收站文件
trash-rm 删除回收站文件

用法

  • 移动文件到回收站:

    1
    $ trash-put

  • 列出回收站文件:

    1
    2
    3
    4
    $ trash-list
    2008-06-01 10:30:48 /home/andrea/bar
    2008-06-02 21:50:41 /home/andrea/bar
    2008-06-23 21:50:49 /home/andrea/foo

  • 搜索回收站文件:

    1
    2
    3
    $ trash-list | grep foo
    2007-08-30 12:36:00 /home/andrea/foo
    2007-08-30 12:39:41 /home/andrea/foo

  • 恢复回收站文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ trash-restore
    0 2007-08-30 12:36:00 /home/andrea/foo
    1 2007-08-30 12:39:41 /home/andrea/bar
    2 2007-08-30 12:39:41 /home/andrea/bar2
    3 2007-08-30 12:39:41 /home/andrea/foo2
    4 2007-08-30 12:39:41 /home/andrea/foo
    What file to restore [0..4]: 4
    $ ls foo
    foo

  • 删除所有回收站文件:

    1
    $ trash-empty

  • 删除回收站中 n 天前被回收的文件:

    1
    $ trash-empty <days>

  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $ date
    Tue Feb 19 20:26:52 CET 2008
    $ trash-list
    2008-02-19 20:11:34 /home/einar/today
    2008-02-18 20:11:34 /home/einar/yesterday
    2008-02-10 20:11:34 /home/einar/last_week
    $ trash-empty 7
    $ trash-list
    2008-02-19 20:11:34 /home/einar/today
    2008-02-18 20:11:34 /home/einar/yesterday
    $ trash-empty 1
    $ trash-list
    2008-02-19 20:11:34 /home/einar/today

  • 只删除符合某种模式的文件:

    1
    $ trash-rm \*.o

    注意:要用双引号圈住模式来避免 shell 拓展。

常见问题

  • 如何创建顶级 .Trash 目录?

    1
    2
    3
    sudo mkdir --parent /.Trash
    sudo chmod a+rw /.Trash
    sudo chmod +t /.Trash

  • 我能把 rm 的别名设置为 trash-put 吗?

    可以,但不应该这样做。以前我觉得这是个好主意,但现在我不觉得。

    虽然 trash-put 的界面看起来与 rm 兼容,但它们有不同的语法,这些差异会导致一些问题。比如,用 rm 删除目录时需要 -R , trash-put 则不需要。

    但有时候我忘记用 trash-put 了,真的不能给 rm 设置别名吗?

  • 你可以给 rm 设置一个别名来提醒你不要使用它:

    1
    alias rm='echo "This is not the command you are looking for."; false'

  • 如果你真的要用 rm ,那就在 rm 前加上斜杠来取消别名:

    1
    \rm file-without-hope

    注意,Bash 别名是有在交互式界面才有效,所以使用这个别名不会影响使用 rm 的脚本。

  • 被移动到回收站的文件在哪?从 home 分区移动到回收站的文件在这:

    1
    ~/.local/share/Trash/

  • 删除文件test.tex, 直接命令输入

    1
    mv -t ~/.local/share/Trash/files --backup=t test.tex

  • shell中取别名

    ~/.zshrc 或 ~/.bashrc
    1
    alias del='mv -t ~/.local/share/Trash/files --backup=t'

  • 使用rl命令查看回收站的内容

    ~/.zshrc 或 ~/.bashrc
    1
    2
    3
    4
    5
    6
    alias rl='ls ~/.local/share/Trash/files'
    alias ur=undelfile
    undelfile()
    {
    mv -i ~/.local/share/Trash/files/$@ ./
    }

  • 使之立刻生效

    1
    2
    source ~/.zshrc
    source ~/.bashrc

注意:文件~/.zshrc针对zsh配置,~/.bashrc针对bash配置。

01. CupPy 概览

今天我们来聊聊一个在 Python 数据科学领域中日益受到关注的库——CuPy。

什么是 CuPy?

CuPy 是一个开源的 Python 库,它的设计初衷是为了使得在 GPU 上的计算变得简单快捷。

它提供了与 NumPy 非常相似的 API,这意味着如果你已经熟悉 NumPy,那么使用 CuPy 将会非常容易。

CuPy 的亮点在于它能够利用 NVIDIA GPU 来加速计算,这在处理大规模数据时尤其有用。

https://github.com/cupy/cupy

为什么选择 CuPy?

  • 速度提升显著:根据多个来源的数据,CuPy 在某些操作上比 NumPy 快了几十甚至几百倍。这对于数据科学和机器学习等领域的应用来说,意味着更高效的数据处理和分析能力。
  • 易于上手:CuPy 的接口设计遵循 NumPy,这使得那些已经熟悉 NumPy 的用户可以轻松迁移到 CuPy。
  • 广泛的应用场景:从深度学习到图像处理,CuPy 都能提供强大的支持。

安装 CuPy

安装 CuPy 相当简单。你只需要使用 pip 命令:

1
2
3
4
5
6
7
8
9
10
11
# For CUDA 11.2 ~ 11.x
pip install cupy-cuda11x

# For CUDA 12.x
pip install cupy-cuda12x

# For AMD ROCm 4.3
pip install cupy-rocm-4-3

# For AMD ROCm 5.0
pip install cupy-rocm-5-

一个简单的例子

让我们来看一个简单的例子,对比一下 NumPy 和 CuPy 在处理同样任务时的速度差异。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np
import cupy as cp
import time

# 使用 NumPy 创建一个大数组
start_time = time.time()
numpy_array = np.random.rand(10000, 10000)
numpy_result = numpy_array ** 2
print("NumPy 时间:", time.time() - start_time)

# 使用 CuPy 完成同样的任务
start_time = time.time()
cupy_array = cp.random.rand(10000, 10000)
cupy_result = cupy_array ** 2
print("CuPy 时间:", time.time() - start_time)

NumPy 时间:3.474796772003174

CuPy 时间:0.0693259145678

在这个例子中,我们创建了一个大型数组,并计算了它的平方。

我们会发现,使用 CuPy 完成同样的任务所需的时间远少于 NumPy,速度提升了 50 倍。

一个更酷的性能对比

创建一个 3D NumPy 数组并执行一些数学函数。time.time()

1
2
3
4
5
6
7
8
9
10
11
import time

# NumPy and CPU Runtime
s = time.time()
x_cpu = np.ones((1000, 100, 1000))
np_result = np.sqrt(np.sum(x_cpu**2, axis=-1))
e = time.time()
np_time = e - s
print("Time consumed by NumPy: ", np_time)

Time consumed by NumPy: 0.5474584102630615

同样,创建一个 3D CuPy 数组,执行数学运算,并为其计时以提高性能。

1
2
3
4
5
6
7
8
9
# CuPy and GPU Runtime
s = time.time()
x_gpu = cp.ones((1000, 100, 1000))
cp_result = cp.sqrt(cp.sum(x_gpu**2, axis=-1))
e = time.time()
cp_time = e - s
print("\nTime consumed by CuPy: ", cp_time)

Time consumed by CuPy: 0.001028299331665039

为了计算差异,我们将 NumPy 时间除以 CuPy 时间

1
2
3
4
diff = np_time/cp_time
print(f'\nCuPy is {diff: .2f} X time faster than NumPy')

CuPy is 532.39 X time faster than NumPy

在使用 CuPy 时,我们似乎获得了超过 500 倍的性能提升

02. 使用示例

CuPy 的基础知识

在本节中,我们将比较 CuPy 和 Numpy 的语法,它们有 95% 的相似度。

  • 首先使用 Python 列表创建一个 NumPy 和 CuPy 数组,之后我们将计算向量的范数。
1
2
3
4
5
6
7
8
9
10
import cupy as cp
import numpy as np
x = [3, 4, 5]
x_np = np.array(x)
x_cp = cp.array(x)
l2_np = np.linalg.norm(x_np)
l2_cp = cp.linalg.norm(x_cp)
print("Numpy: ", l2_np)
print("Cupy: ", l2_cp

正如我们所看到的,我们得到了类似的结果。

1
2
Numpy:  7.0710678118654755
Cupy: 7.0710678118654755
  • 要将 NumPy 转换为 CuPy 数组,只需使用 .cp.asarray(X)
1
2
3
x_array = np.array([10, 22, 30])
x_cp_array = cp.asarray(x_array)
type(x_cp_array)

cupy.ndarray

  • 或者,使用 将 CuPy 转换为 Numpy 数组。.get()
1
2
x_np_array = x_cp_array.get()
type(x_np_array)

numpy.ndarray

CuPy 高级应用示例

  • 图像处理:边缘检测

图像处理是 CuPy 的一个重要应用领域。以下是一个使用 CuPy 进行边缘检测的示例:

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
import cupy as cp
import cv2

def edge_detection(image_path):
# 读取图像
image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
image_gpu = cp.asarray(image)

# Sobel 边缘检测算子
sobel_x = cp.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], dtype=cp.float32)
sobel_y = cp.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]], dtype=cp.float32)

# 应用算子
edge_x = cp.abs(cp.signal.convolve2d(image_gpu, sobel_x, mode='same'))
edge_y = cp.abs(cp.signal.convolve2d(image_gpu, sobel_y, mode='same'))

# 合并边缘
edge = cp.sqrt(cp.square(edge_x) + cp.square(edge_y))

# 将结果转换回 CPU 并显示
result = cp.asnumpy(edge)
cv2.imshow('Edge Detection', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 使用示例
edge_detection('path_to_your_image.jpg')

这个示例展示了如何使用 CuPy 在 GPU 上进行图像的边缘检测,这对于图像分析和计算机视觉应用非常有用。

  • 大规模数据运算:矩阵乘法

CuPy 在处理大规模数据运算时表现出色。下面是一个矩阵乘法的示例:

1
2
3
4
5
6
7
8
9
10
11
12
import cupy as cp
import time

# 创建大型随机矩阵
a_gpu = cp.random.rand(10000, 10000)
b_gpu = cp.random.rand(10000, 10000)

# 执行矩阵乘法
start_time = time.time()
c_gpu = cp.dot(a_gpu, b_gpu)
cp.cuda.Stream.null.synchronize() # 确保计算完成
print("CuPy 矩阵乘法时间:", time.time() - start_time)

这个示例展示了 CuPy 在执行大规模矩阵乘法时的高效性,这对于科学计算和数据分析尤其重要。

  • 深度学习:简单的神经网络

CuPy 也可以用于构建和训练简单的神经网络。以下是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import cupy as cp

def sigmoid(x):
return 1 / (1 + cp.exp(-x))

# 随机初始化权重
weights = cp.random.rand(3, 1)

# 示例输入
inputs = cp.array([[1, 0, 1],
[1, 1, 1],
[0, 0, 1]])

# 前向传播
outputs = sigmoid(cp.dot(inputs, weights))

print(outputs)

这个示例展示了如何使用 CuPy 进行简单的神经网络前向传播计算。

以上示例展示了 CuPy 在不同领域的应用,包括图像处理、大规模数据运算和深度学习。

03. Numpy、Cupy 和 Pytorch

CuPy 和 NumPy 之间的区别

别问我有什么区别,问就是几乎一样样。实在要知道到底有什么区别,参考Differences between CuPy and NumPy

Cupy 与 Numpy 互转

1
2
3
4
5
6
7
8
import cupy as cp
import numpy as np

# cupy->numpy
numpy_data = cp.asnumpy(cupy_data)

# numpy->cupy
cupy_data = cp.asarray(numpy_data)

Cupy 与 Pytorch 互转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 需借助中间库 dlpack
# cupy.array<–>Dlpack.Tensor<–>torch.Tensor

from cupy.core.dlpack import toDlpack
from cupy.core.dlpack import fromDlpack
from torch.utils.dlpack import to_dlpack
from torch.utils.dlpack import from_dlpack
import torch

# pytorch->cupy
cupy_data = fromDlpack(to_dlpack(tensor_data))

# cupy->pytorch
tensor_data = from_dlpack(toDlpack(cupy_data)

Numpy 与 Pytorch 互转

1
2
3
4
5
6
7
8
import numpy as np
import torch

# pytorch->numpy
numpy_data = tensor_data.numpy()

# numpy->pytorch
tensor_data = torch.from_numpy(numpy_data)

抱个拳 总个结

Beyond NumPy

让我们以一张表结束:最快的 CPU VS 最快的 GPU。

CuPy 是一个强大的工具,它能够显著提高数据处理的速度。

对于那些希望在数据科学和机器学习领域进一步提升效率的朋友们,CuPy 绝对值得一试。

diary.sh 开发说明

自从网易、新浪等博客网站关闭后,我决定使用 HexoGithubGiteeGitlab 等代码托管平台,借助其 Pages 功能来部署自己的博客。但是每次都使用 Hexo 的标准命令进行操作,步骤上确实很繁琐。随着时间的推移,博客内容越来越多,于是就需要一个能够管理博客并方便发布博客的工具。为了达成这个目标,diary.sh 应运而生!这个脚本一直作为我的私人程序使用,但由于前期编写 Shell 代码的水平有限,使得脚本的通用性不佳,同时一些功能的实现也不太理想。在熟练掌握 Shell 后,我改进了程序,推出了通用版本,并将版本号升级为 V8.0。在新版中,个人信息将以配置文件的形式由作者自行填写,脚本中不再保留任何个人信息。

简明信息

diary.sh
1
2
3
4
5
6
7
# Program  : diary.sh
# Author : fengzhenhua
# Email : fengzhenhua@outlook.com
# CopyRight: Copyright (C) 2022-2025 FengZhenhua(冯振华)
# License : Distributed under terms of the MIT license.
# History : 2024年04月20日, 升级了菜单选择系统,同时去除个人信息写在脚本中的问题,使diary.sh成为通用程序
# 2024年04月22日, 修改COMMENT为主板名,可以识别出发布博客的机器,比使用主机名更可靠升级V8.3

安装

Install diary.sh
1
2
sudo curl -o /usr/local/bin/diary https://gitlab.com/fengzhenhua/script/-/raw/usbmain/diary.sh\?inline\=false 
sudo chmod +x /usr/local/bin/diary

使用方法: diary -h 获取帮助。

发布仓库

已经脚本程序分别发布于gitlabgitee, 请您自行前往下载:

可用脚本为:

脚本 作用
arcsetup.sh 配置ArchLinux
diary.sh 管理GitLab博客
ugit.sh U盘仓库管理, 单U盘版
neougit.sh U盘仓库管理, 多U盘版
updatehost.sh 升级host访问github
translatorGD.py Goldendict 添加网络翻译

1. Git配置

  1. 安装Git:https://git-scm.com/
  2. 本地命令行生成密钥绑定GitHub账号
1
2
3
4
5
6
7
8
# 输入命令生成密钥对,替换成自己邮箱,然后一路回车
ssh-keygen -t rsa -C "youremail@example.com"

# 将生成的公钥打印出来复制,将这串文本复制粘贴到GitHub的Setting->SSH and GPG keys中
cat ~/.ssh/id_rsa.pub

# 输入命令检查是否绑定成功,输入yes后,如果出现Hi,xxx!则绑定成功
ssh -T git@github.com

3. 配置用户名和邮箱信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 查看配置信息,一开始为空
git config --list

# 全局配置,对所有代码库生效
git config --global user.name "你的名字"
git config --global user.email "你的邮箱"


# 局部配置,只对当前的代码库有效
git config --local user.name "你的名字"
git config --local user.email "你的邮箱"

# 配置后,远程仓库提交的commit里对应的用户即为 user.name

2. Git基本概念

  1. 本地仓库:本地仓库上存放所有相关的文件,具体可分为工作区、暂存区和仓库区,工作区即项目文件夹下不包含.git文件夹的所有文件,暂存区和仓库区则在.git文件夹下
  2. 工作区:即我们工作的文件夹,在里面进行文件的增删改操作
  3. 暂存区:临时保存工作区上的改动,通过git add操作将工作区的修改同步到暂存区
  4. 仓库区:当执行git commit操作时,将暂存区上的所有变动同步到本地仓库
  5. 远程仓库:GitHub/GitLab上保存的仓库,通过git push将本地仓库同步到远程仓库,也可以通过git fetch/pull将远程仓库同步到本地仓库
Git基本概念

3. Git基本操作

创建版本库

创建版本库有两种方式,一种是将本地的文件夹直接变成一个git仓库,另一种是直接将远程的仓库克隆到本地

1
2
git init # 将本地文件夹变为一个git仓库
git clone <url> #将远程仓库克隆到本地

修改与提交操作

1
2
3
4
5
git add <file> # 将单个文件从工作区添加到暂存区
git add . # 将所有文件添加到暂存区
git commit -m "messenge" # 将暂存区文件提交到本地仓库
git status # 查看工作区状态,显示有变更的文件。
git diff # 比较文件的不同,即暂存区和工作区的差异。

远程操作

1
2
3
4
5
6
git push origin master # 将本地的master分支推送到远程对应的分支
git pull # 下载远程代码并合并,相当于git fetch + git pull
git fetch # 从远程获取代码库,但不进行合并操作

git remote add origin <url> # 将远程仓库与本地仓库关联起来
git remote -v # 查看远程库信息

撤销与回退操作

撤销操作:当修改了工作区/暂存区的文件,但是还没有commit时,想要撤销之前的操作:

1
2
3
4
5
6
7
8
9
# 场景1:当你改乱了工作区某个文件的内容,但还没有add到暂存区
git checkout <file> # 撤销工作区的某个文件到和暂存区一样的状态

# 场景2:当乱改了工作区某个文件的内容,并且git add到了暂存区
git reset HEAD <file> # 第1步,将暂存区的文件修改撤销掉
git checkout <file> # 第2步,将工作区的文件修改撤销掉

# 场景3:乱改了很多文件,想回到最新一次提交时的状态
git reset --hard HEAD # 撤销工作区中所有未提交文件的修改内容

回退操作:当已经进行了commit操作,需要回退到之前的版本:

1
2
3
4
5
git reset --hard HEAD^ # 回退到上次提交的状态
git reset --hard HEAD~n # 回退到n个版本前的状态
git reset --hard HEAD commitid # 回退到某一个commitid的状态
git reset --soft HEAD commitid # 回退到某一个commitid的状态,并且保留暂存区的内容
git reset --mixed(默认) HEAD commitid # 回退到某一个commitid的状态,并且保留工作区的内容

关于reset三种模式的说明:

reset的三种模式

4. Git分支管理

git的最强大之处就在于分支管理了,具体有两种应用场景:

  1. 多人协作:每个人都基于主分支创建一个自己的分支,在分支上进行开发,然后再不断将写好的代码合并到主分支
  2. 自己修复bug/增加feature:创建一个bug分支或者feature分支,写好代码后合并到自己的分支然后删除bug/feature分支
1
2
3
4
5
6
git branch <name> # 创建分支
git checkout <name> # 切换到某个分支
git checkout -b <name> # 创建并切换到新分支,相当于同时执行了以上两个命令
git merge <name> # 合并某个分支到当前分支中,默认fast forward
git branch -a # 查看所有分支
git branch -d <name> # 删除分支

5. Git多人协作

多人协作在同一个分支上进行开发的工作模式:

  1. 首先,可以试图用git push origin <branch-name>推送自己的修改;
  2. 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
  3. 如果合并有冲突,则解决冲突,并在本地提交;
  4. 没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功!
  5. 如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>

6. Git分支重命名

  • 在当前分支时
1
git branch -m new_branch_name
  • 当不在当前分支时
1
git branch -m old_branch_name new_branch_name

如果是已经推送到远端,应该怎么做呢?

重命名远端分支(假设是在当前分支,并且远端分支与本地分支名是一致的)

  • 重命名本地分支
1
git branch -m new_branch_name
  • 删除远程分支
1
git push --delete origin old_branch_name
  • 上传新命名的本地分支
1
git push origin new_branch_name
  • 关联修改后的本地分支与远程分支
1
git branch --set-upstream-to origin/new_branch_name

7. 参考

  1. Git教程 | 菜鸟教程
  2. Git教程 - 廖雪峰的官方网站

简介

rsync 是一个常用的 Linux 应用程序,用于文件同步。它可以在本地计算机与远程计算机之间,或者两个本地目录之间同步文件(但不支持两台远程计算机之间的同步)。它也可以当作文件复制工具,替代cp和mv命令。它名称里面的r指的是 remote,rsync 其实就是"远程同步"(remote sync)的意思。与其他文件传输工具(如 FTP 或 scp)不同,rsync 的最大特点是会检查发送方和接收方已有的文件,仅传输有变动的部分(默认规则是文件大小或修改时间有变动)。

安装

1
sudo pacman -S rsync

用法

-r参数

本机使用 rsync 命令时,可以作为cp和mv命令的替代方法,将源目录同步到目标目录。

1
rsync -r 源目录  目标目录

参数-r表示递归,复制所有包括子目录的文件,且-r也是必须的,否则rsync运行不会成功。

-a参数

-a参数可以替代-r,除了可以递归同步以外,还可以同步元信息(比如修改时间、权限等)。由于 rsync 默认使用文件大小和修改时间决定文件是否需要更新,所以-a-r更有用。下面的用法才是常见的写法。

1
rsync -a source destination
阅读全文 »

最初只是想用U盘作为远程仓库,解决现存托管平台的若干问题。但是,随着近两天的考虑,逐步实现了本地U盘仓库及时同步+联网同步(可选择仓库,用来发布软件)的功能,这种做法的优点是:

  • 所有仓库在本地U盘, 可以解决网络托管平台访问速度慢、容量有限、费用高、隐私保护等问题。
  • 对于不能联网的电脑,可以使用U盘仓库随时随地编辑代码,离线同步。
  • 对于开源代码,可以设置网络,一条命令实现本地+U盘+网络托管平台同步功能,及时发布最新软件。
  • 配置文件: 网络托管平台githabgitlabgitee等已经配置了ssh或公开的仓库。
    ~/.ugitrcf
    1
    2
    3
    4
    example:
    gitee https://github.com/project.git
    gitee git@gitee_fengzhenhua:fengzhenhua
    gitlab git@gitlab_fengzhenhua:fengzhenhua

配置文件设置后,脚本自动启用网络同步功能。~/.ugitrcf前2行格式范例,不起作用,,您的有效配置应当

ugit 项目

安装脚本

  • 安装版本

    Install ugit.sh
    1
    2
    sudo curl -o /usr/local/bin/ugit https://gitlab.com/fengzhenhua/script/-/raw/usbmain/ugit.sh\?inline\=false 
    sudo chmod +x /usr/local/bin/ugit

    注意:单U盘版是第一代试验性的方案,目前已经实现多U盘版,且功能更加实用,所以单U盘版不再维护。其存在的问题主要是根据U盘名称识别U盘仓库,如果用户修改了U盘名称或使用了同名的其他U盘,则会出现问题,所以不建议大家使用单U盘版。

  • 安装版本

    Install neougit.sh
    1
    2
    sudo curl -o /usr/local/bin/ugit https://gitlab.com/fengzhenhua/script/-/raw/usbmain/neogit.sh\?inline\=false 
    sudo chmod +x /usr/local/bin/ugit

选项及功能

各项操作前,先将U盘插入到Linux电脑的USB接口, 如果没有U盘连接电脑则会出现提示。

命令 功能 备注
ugit -a 克隆全部U盘仓库到本地仓库 2024年04月17日
ugit -ad 关联远程网络仓库 2024年04月19日,需设置~/.ugitrcf
ugit -b 上传全部本地仓库到U盘仓库和网络仓库 2024年04月19日
ugit -c 克隆U盘中已经建立的仓库 2024年04月16日
ugit -h 显示帮助 2024年04月19日
ugit -l 列出U盘仓库 2024年04月18日
ugit -ll 列出本地仓库 仅适用多U盘版2024-04-22
ugit -lr 列出U盘仓库 仅适用多U盘版2024-04-22
ugit -n 新建U盘仓库并克隆到本地 2024年04月16日
ugit -p 上传全部本地仓库到网络仓库 2024年04月18日
ugit -r 删除U盘中已经建立的仓库 2024年04月16日
ugit -s 同步本地、U盘、网络 2024年04月23日
ugit -u 联网升级 2024年04月18日
ugit -v 显示版本 2024年04月19日
ugit 自动更新本机克隆自U盘的仓库 2024年04月17日
ugit.sh -i 安装脚本到/usr/local/bin/ugit 2024年04月16日
  • 2024年04月16日, 获得使用U盘作为Git仓库的方法后,为了尽快投入工作,连夜编写了自动化脚本ugit.sh,直接使用curl命令安装可以保证始终使用的是最新版。
  • 2024年04月19日, ugit.sh目前仅支持Linux系统,欢迎您移植到Windows平台。
  • 2024年04月22日, neougit.sh发布,版本号V3.1, 支持多U盘
  • 2024年04月22日, 修复关联远程仓库bug, 升级版本号V3.3
  • 2024年04月23日, 增加-s同步选项,升级版本号V3.5, 对于U盘中已经删除的仓库,但是另一台电脑上尚没有删除的,此选项将其移除到回收站

技术细节

  1. 插入电脑U盘, 假设您的U盘名字为159xxxxxxxx, 您的Linux用户名为wheel, 则在ArchLinuxU盘的地址为

    1
    /run/media/wheel/159xxxxxxxx

  2. U盘创建空仓库test, 实际就是建立一个文件夹作为git的远程仓库

    1
    2
    3
    4
    cd /run/media/wheel/159xxxxxxxx
    mkdir test
    cd test
    git init --bare

    注意:选项--bare必须有, 如果git仓库创建成功,则提示消息为

    1
    Initialized empty Git repository in /run/media/wheel/150xxxxxxxx/test/

  3. ,初始化本地仓库

    1
    2
    cd ~/test-your
    git init

  4. 建立远程仓库连接,编辑本地git配置文件,写入如下内容,关联仓库及其分支

    ~/test-your/.git/config
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    [remote "usb"]
    url = /run/media/wheel/159xxxxxxxx/test/
    fetch = +refs/heads/*:refs/remotes/usb/*
    [branch "master"]
    remote = usb
    merge = refs/heads/master

    注意:文件~/test-your/.git/config, 中的usb是您对远程仓库的别名,可以任意取定。

  5. 创建README.md文件,同第一次推送文件,注意中。

    1
    2
    3
    4
    5
    git pull
    touch README.md
    git add .
    git commit -m "first push"
    git push

  6. 拉取文件, 注意中。

    1
    git pull

  7. 在新电脑上克隆项目

    1
    git clone /run/media/wheel/159xxxxxxxx/test

    注意:对于clone下来的项目,pushpull和普通的git操作没有区别。如果不像上面这样编辑默认的默认的仓库及分支,则网络上的教程在U盘上建立git仓库,移动的“私有云”完成的配置的话应当使用命令pull usb master拉取,使用push usb master推送,其显然不如此处的配置便捷。

实现此脚本的最初说明 常用的代码托管平台有:githubgitlabgitee. github访问不是很稳定,同时只有付费版的才可以建立私有仓库,否则就是开放的。gitlab支持私有仓库的建立,但是注册gitlab需要google接收验证码,这在国内不容易做到,再者仓库容量5G, 有些不够用. gitee是国内的,优点是速度快,缺点容量也是5G,还有一些其他因素导致也不适合存放隐私文件。上述这些都是自己准备一个U盘建立自己的远程仓库的理由,优点无非是容量大,成本低,速度快,但也不是没有缺点,如果使用的U盘质量不过关那就面临资料损失的风险,所以.

在使用LaTeX生成目录超链接时,默认超链接的样式为带红色边框,这被多数人认为不美观,所以本文给出去掉边框的方法。

  • 在引用hyperref宏包时,应当把它放在最后一个位置,因为它修改了若干命令,如果有其他的宏包也修改了常规命令,则编译文件时会出错。

  • 宏包调用时的设置

    • 使用pdfborder选项

      1
      \usepackage[colorlinks=false, pdfborder={0 0 0}]{hyperref}

    • 使用hidelinks选项

      1
      \usepackage[hidelinks]{hyperref}

    • 修改链接颜色

      1
      2
      3
      4
      \usepackage[
      colorlinks=true,
      linkcolor=black
      ]{hyperref}

  • 使用hyperref的配置选项

    • 使用hidelinks隐藏链接

      1
      \hypersetup{hidelinks}

    • 修改链接颜色

      1
      2
      3
      4
      \hypersetup{
      colorlinks=true,
      linkcolor=black
      }