git 拉取所有 branch 和 tag 到本地并推送到远程

需要一个正常的可工作仓库,而不是裸镜像仓库。以下是在不使用 --mirror 选项的情况下,拉取所有分支和标签并推送到新仓库的步骤:

步骤 1: 克隆源仓库

首先,正常克隆源仓库:

# 克隆源仓库(默认只会检出 main 或 master 分支)
git clone <源仓库URL> repo-copy
cd repo-copy

步骤 2: 获取所有远程分支

默认情况下,git clone 只会创建和检出默认分支。你需要额外步骤来获取和创建所有远程分支的本地跟踪:

# 获取所有远程分支的信息
git fetch --all

# 为每个远程分支创建本地跟踪分支
git branch -r | grep -v '\->' | while read remote; do
    git branch --track "${remote#origin/}" "$remote"
done

# 拉取所有分支的最新更改
git fetch --all
git pull --all

步骤 3: 获取所有标签

确保所有标签也被获取:

# 拉取所有标签
git fetch --tags

步骤 4: 添加目标远程仓库并推送所有内容

# 添加目标远程仓库
git remote add target <目标仓库URL>

# 推送所有分支到目标仓库
git push target --all

# 推送所有标签到目标仓库
git push target --tags

一键完成脚本

下面是一个完整的脚本,可以一键完成整个过程:

# 克隆源仓库
git clone <源仓库URL> repo-copy
cd repo-copy

# 获取所有远程分支信息
git fetch --all

# 为远程分支创建本地跟踪分支
git branch -r | grep -v '\->' | while read remote; do
    git branch --track "${remote#origin/}" "$remote"
done

# 拉取所有分支和标签的最新更改
git fetch --all
git pull --all
git fetch --tags

# 添加目标远程仓库
git remote add target <目标仓库URL>

# 推送所有内容到目标仓库
git push target --all
git push target --tags

echo "所有分支和标签已成功推送到目标仓库"

简化的替代方法(适用于较新版本的 Git)

在较新版本的 Git 中,你可以使用以下简化命令:

# 克隆仓库
git clone <源仓库URL> repo-copy
cd repo-copy

# 获取所有分支并设置本地跟踪
git fetch origin
git checkout -b local_branch origin/remote_branch  # 对需要的每个远程分支重复此命令

# 获取所有标签
git fetch --tags

# 添加新远程仓库并推送
git remote add target <目标仓库URL>
git push target --all
git push target --tags

注意事项

  1. 这些命令会在本地创建所有远程分支的跟踪分支,使你能够在它们之间切换
  2. 如果仓库很大或分支很多,这个过程可能需要一些时间
  3. 确保你有足够的磁盘空间来存储完整的仓库及其历史记录
  4. 默认情况下,这不会推送任何 Git LFS 对象,如果你使用 Git LFS,可能需要额外的步骤

Rails 性能分析工具 rack-mini-profiler 和 bullet

rack-mini-profiler 和 bullet 是ruby 开发中两个广受欢迎的性能分析工具。

Bullet 更加实用,提得建议更加直接有效,rack-mini-profiler 信息丰富,需要更细致的排查时使用。

rack-mini-profiler

rack-mini-profiler 是一个轻量级的性能分析工具,它能够实时显示页面加载时间和数据库查询详情。在页面右上角显示一个小窗口,展示了页面加载的总时间,并可以展开查看详细的性能数据。它的主要特点包括:

  • 显示详细的 SQL 查询时间和调用栈
  • 支持查看内存使用情况
  • 可以分析 AJAX 请求
  • 提供火焰图分析功能
  • 支持对特定请求进行采样分析

使用 rack-mini-profiler 只需要在 Gemfile 中添加 gem 'rack-mini-profiler',并重启服务器即可生效。默认情况下它会在开发环境中自动启用。

Bullet

Bullet 则专注于解决 N+1 查询问题和检测未使用的预加载。N+1 查询是 Rails 应用中常见的性能问题,当获取关联数据时可能导致过多的数据库查询。Bullet 通过以下方式帮助开发者:

  • 实时检测 N+1 查询问题
  • 提示潜在的需要预加载的关联
  • 识别不必要的预加载
  • 支持多种通知方式(控制台、浏览器通知等)

要使用 Bullet,需要在 Gemfile 中添加 gem 'bullet',并在 config/environments/development.rb 中进行配置:

config.after_initialize do
  Bullet.enable = true
  Bullet.alert = true
  Bullet.rails_logger = true
end

这两个工具的结合使用能够帮助开发者全面了解应用的性能状况,及时发现和解决性能问题。rack-mini-profiler 提供了整体性能的详细视图,而 Bullet 则专注于数据库查询优化,它们互相补充,是 Rails 开发中不可或缺的性能优化工具。

参考文献

  1. rack-mini-profiler GitHub: https://github.com/MiniProfiler/rack-mini-profiler
  2. Bullet GitHub: https://github.com/flyerhzm/bullet
  3. Ruby on Rails Guides: https://guides.rubyonrails.org/performance_testing.html
  4. “Optimization and Performance Monitoring in Ruby on Rails”, RailsConf 2021

Rails Active Record 常用命令

主要命令

rake db:migrate
rake db:rollback

rake db:migrate:up
rake db:migrate:down

rake db:migrate:redo

指定版本号的回滚

rake db:migrate:down VERSION=20141119130134

回滚最近几个迁移

rake db:rollback STEP=n

n 代表个数。注意:是最近几个,它们会被一起移除。

其它类似命令:

只执行指定版本号的迁移

rake db:migrate VERSION=20141119130134

只执行最近几次迁移

rake db:migrate STEP=n

回滚、然后重新执行最近几次迁移

rake db:migrate:redo STEP=n

References

Rails Rake 简介与编写

来源:Rake 简介与编写

Rake 用法简介

rake 简介

Rake 的意思是 Ruby Make,一个用 ruby 开发的代码构建工具。

1.以任务的方式创建和运行脚本 当然,你可以用脚本来创建每一个你希望自动运行的任务。但是,对于大型的应用来说,你几乎总是需要为数据库迁移 (比如 Rails 中 db:migrate 任务)、清空缓存、或者代码维护等等编写脚本。对于每一项任务,你可能都需要写若干脚本,这会让你的管理变得复杂。那么,把它们用任务的方式整理到一起,会让管理变得轻松很多。

2.追踪和管理任务之间的依赖 Rake 还提供了轻松管理任务之间依赖的方式。比如,”migrate”任务和”schema:dump”任务都依赖于 “connect_to_database”任务,那么在”migrate”任务调用之前,”connect_to_database”任务都会被执行。

rake 的编写

首先 rake 文件的后缀是.rake,存放在 lib/tasks 文件夹下。 可以通过 rake –tasks 来查看当前程序下所已存在的 rake 脚本。 看下面这个例子:

desc "study rake about rails"    #desc 是Rake定义的方法,表示对下面定义任务的描述.这个描述会在使用Rake --tasks(或者Rake -T)命令时输出在屏幕上.
task :study_rake do         #cmd 命令行中执行 rake study_rake 开始执行脚本,task是Rake最重要的方法.它的方法定义是:task(args, &block).任务体是一个block。
  %w(a b c).each do |d|
    puts d   #编写你所需的功能代码。
  end 
end

这就是创建了一个 rake 脚本,这个脚本的作用是循环遍历 [“a”, “b”, “c”] 这个数组。

依赖关系和命名空间

依赖关系

desc "rake1"   
task :rake1 do   
    puts "rake1"   
end   

desc "rake2"   
task ::rake2=> :rake1 do   
    puts "rake2"   
end  

输出结果:

rake1
rake2

命名空间

namespace :today do
desc "rake1"   
task :rake1 do   
    puts "rake1"   
end      
end

那执行命令就是:rake today:rake1

在一个任务中调用另外一个任务

desc "today rake"   
task :today do   
  Rake::Task["rakes:rake1"].invoke
  Rake::Task["rakes:rake2"].invoke
  Rake::Task["rakes:rake3"].invoke
end  
namespace :rakes do
desc "rake1"   
task :rake1 do   
    puts "rake1"   
end  
desc "rake2"   
task :rake2 do   
    puts "rake2"   
end  
desc "rake3"   
task :rake3 do   
    puts "rake3"   
end  
end

默认任务

task :default => [:today]  

Rails 中的 Rake 任务

Rails 预定义了大量的 Rake 任务,在 Rails 应用的开发过程中,你想必已经在大量使用它们了。在 Rails 中,所有的 Rake 任务都放在 rails 目录的 lib/tasks 目录下 (在作者的环境下是 C:\Ruby\lib\ruby\gems\1.8\gems\rails-2.3.5 \lib\tasks),所有的 rake 任务都以.rake 作为后缀名,这些以.rake 结尾的文件会被自动加载到你的环境中。你可以到一个已有的 Rails 工程根目录下键入 rake –tasks,可以看到很多的 rake 任务已经为你整装待发了。

E. 参考资料 http://blog.sina.com.cn/s/blog_4748c4d20100y9iu.html

References

如何调试 Vim 脚本

来源: 如何调试 Vim 脚本

使用 -D 参数可以开启 Debug 模式, 在 Debug 模式中可以使用 cont, next, interrupt, step, quit 等调试命令, 以及 breakadd, breakdel 来添加和移除断点。 使用 -u 来禁止加载任何配置文件,使用 :source 命令逐个加载。 使用 :set verbose:set verbosefile配置变量 可以设置日志级别和输出文件, -V 启动参数也可以起到同样的作用。

日志级别

在介绍 Debug 之前有必要先介绍如何查看运行日志,本文只介绍到日志级别的设置方法和日志文件的设置方法。 日志级别是由 verbose 配置变量 控制的。这是一个默认为零的数字,级别越高输出越详细。 verbose 非零时 Vim 就会在当前窗口显示日志信息,例如 :set verbose=20 就可以开启几乎所有日志。 这些级别的描述如下:

>= 1    读写 viminfo 文件时
>= 2    当 ":source" 一个文件时,通常是载入一个配置文件
>= 5    所有搜索到的 tag 文件和 include 文件
>= 8    执行到 autocommands 的文件
>= 9    每次执行到 autocommand 时
>= 12   每次执行到 function 时
>= 13   产生、捕获、结束处理、忽略一个异常时
>= 14   ":finally" 语句中等待的所有命令
>= 15   每一个执行到的 Ex 命令(截断到 200 字符)

更多 verbose 选项变量的信息可以参考 :help vbs。 日志级别也可以通过 -V 启动参数来设置。例如:

vim -V20 main.cpp

日志文件

如果你试过上述日志级别的设置方式会发现日志直接输出在当前屏幕,这会影响在当前 Vim 中的连贯操作。 我们可以通过 :set verbosefile 把日志输出到文件中。例如把它输出到 vim.log 文件:

set verbosefile=vim.log

然后在另一个 Shell 中 tail 这个文件,我们就可以一边使用 Vim 一边查看它的日志了:

tail -f vim.log

更多 verbosefile 选项变量的信息可以参考 :help verbosefile。 日志文件也可以通过 -V 启动参数来设置。例如设置级别为 20,输出文件名为 vim.log

vim -V20vim.log main.cpp

注意级别与文件名之间不能加空格,且文件名不得以数字开头(否则会被识别为级别的一部分)。

零配置启动

有时为了定位问题,我们可以禁止 Vim 自动加载配置文件和插件,手动地逐个加载 Vim 脚本。 需要先零配置启动 Vim,通常设置 -u 即可:

vim -u NONE main.cpp

如果你在使用 GVim 可能需要使用 -U,具体情况可参考 :help -UStackOverflow。 启动后使用 :source {filename} 命令来逐个加载 Vim 配置即可。

Debug 方法

在启动 Vim 时添加 -D 参数即可开启调试模式,Vim 会在第一行配置文件出中断并进入 Debug 模式:

vim -D main.cpp

中断后会进入 Debug 模式,你可以看到 > 提示符。此时你就可以输入 Debug 命令,操作方式和 gdb 非常类似:

  • cont: 继续执行直到下一个断点。
  • quit: 停止当前过程,继续执行到下一个断点。
  • step: 执行当前断点处的指令,执行完后仍然回到 Debug 模式。
  • next: 与 step 一样,但会直接执行完整个方法调用和文件引入(source)
  • interrupt: 停止当前过程,执行下一个命令前回到 Debug 模式。
  • finish: 执行完当前脚本或方法调用,回到 Debug 模式。

掌握 Debug 命令后下一个事情就是打断点,可以在函数和文件的相应行号处添加断点:

breakadd func [lineNumber] functionName
breakadd file [lineNumber] fileName
breakadd here

同样的语法可以用来移除断点,关键字从 breakadd 换为 breakdel

breakdel func [lineNumber] functionName
breakdel file [lineNumber] fileName
breakdel here

还可以按照编号移除 breakdel {number} 和移除全部 breakdel *。 更详细的参数和命令可以参考 :help debug

小技巧

上述日志和调试命令已经足够定位 Vim 脚本的问题了。 下面介绍几个小技巧可以方便一些场景下的操作:

像 Chrome 控制台一样,可以 Debug 某个命令:

:debug CommandName

也可以直接 debug 某个函数,不需要 Vim 先进入 Debug 模式:

:debug call Foo()

类似地,日志级别也可以在调用函数时进行设置:

:20verbose call Foo()

References

Tailscale 自建 Derp

TL;DR

必需:将 env DERP_DOMAIN 设置为您的域

docker run -e DERP_DOMAIN=derper.your-domain.com -p 80:80 -p 443:443 -p 3478:3478/udp fredliang/derper

也有其他不使用域名的方法,参考文献自行探索

References

Ceph 检查 rbd io 排名

好的,在 Ceph 中查看哪个 RBD (RADOS Block Device) 镜像的 I/O 读写最高,最常用的方法是使用 rbd perf image iotoprbd perf image iostat 命令。

这两个命令都需要指定 存储池 (pool) 的名称,因为 RBD 镜像是存在于特定的存储池中的。

方法一:使用 rbd perf image iotop (推荐)

这个命令会实时显示指定存储池中各个 RBD 镜像的 I/O 统计信息,并默认按总 I/O 操作数 (IOPS) 或总带宽排序,非常直观。

  1. 首先,确定 RBD 镜像所在的存储池。 如果不确定,可以使用 rbd pool lsceph osd lspools 列出所有存储池。
  2. 执行命令:
    rbd perf image iotop 
    <poolname>

将 `

` 替换为实际的存储池名称。 例如,如果你的 RBD 镜像在名为 `rbd_images` 的存储池中: “`bash rbd perf image iotop rbd_images “` 3. **查看输出:** 该命令会持续刷新输出,通常包含以下列: * `image`: RBD 镜像的名称。 * `rd_ops`, `wr_ops`, `total_ops`: 每秒读、写、总操作次数 (IOPS)。 * `rd_bytes`, `wr_bytes`, `total_bytes`: 每秒读、写、总带宽 (Bytes/s)。 输出通常会按 `total_ops` 或 `total_bytes` 降序排列,排在最前面的就是当前 I/O 最高的 RBD 镜像。按 `Ctrl+C` 退出。 **方法二:使用 `rbd perf image iostat`** 这个命令与 `iotop` 类似,也显示 I/O 统计,但格式可能略有不同,有时显示的是累积值或平均值,具体取决于 Ceph 版本和配置。 1. **确定存储池名称。** 2. **执行命令:** “`bash rbd perf image iostat “` 同样,将 ` ` 替换为实际的存储池名称。 例如: “`bash rbd perf image iostat rbd_images “` 3. **查看输出:** 分析输出中的读写 IOPS 和带宽列,找出数值最高的镜像。这个命令也可能持续刷新,按 `Ctrl+C` 退出。 **重要注意事项:** 1. **指定存储池:** 这两个命令都**必须**指定存储池名称。你需要对每个包含 RBD 镜像的存储池分别运行这些命令,才能找到整个集群中 I/O 最高的镜像。 2. **性能计数器:** 这些命令依赖于 Ceph 的性能计数器 (performance counters)。通常这些计数器是默认启用的,但如果遇到问题,可能需要检查相关配置。 3. **权限:** 执行这些命令需要相应的 Ceph 用户权限(通常是 client.admin 或具有针对特定存储池读写权限的用户)。 4. **Ceph 版本:** 命令的具体行为和输出格式可能随 Ceph 版本略有变化。 5. **Ceph Dashboard:** 如果你部署了 Ceph Dashboard(Web UI),通常在 Dashboard 的 “Block” -> “Images” 部分也能方便地查看各个 RBD 镜像的实时性能指标,包括 IOPS 和带宽,并且可以进行排序。这对于图形化监控来说更加友好。 **总结:** 使用 `rbd perf image iotop ` 是查找指定存储池中当前 I/O 活动最密集的 RBD 镜像的最直接和常用的命令行方法。记得要检查所有相关的存储池。

k8s csi-driver-nfs的一个坑

TL;DR

发现 k8s csi 组的社区项目 csi-driver-nfs v4.10v4.11 至少这两个版本存在删除 pv 时会连带将整个根删除的问题。

声明 StorageClass 时虽然支持 subDir ,类似这样:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-aliyun-gz
provisioner: nfs.csi.k8s.io
parameters:
  share: "/csi"
  server: "28364f4a1fa-eok75.cn-guangzhou.nas.aliyuncs.com"
  #server: "172.26.12.20"
  #subDir: "${pvc.metadata.namespace}/${pvc.metadata.name}"
reclaimPolicy: Delete
#volumeBindingMode: WaitForFirstConsumer
volumeBindingMode: Immediate
allowVolumeExpansion: true
mountOptions:
#  - nolock,tcp,noresvport
  - vers=3,nolock,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport

但如果类似这样使用 subDir 声明路径,同命名空间下的其他 pvc 删除,会导致整个 subDir 根目录都被删除。目前官方 pr 已经修复,但实测还是有问题,有空再研究一下代码,不知道是不是刻意为之。

回溯 issuer 历史发现是有人提了 bug 发现目录下出现很多空目录,认为需要删除,修复者修复这一问题时错误的将整个根删除。为了规避这一问题,暂时回退到更早的 4.9 版本 csi

helm upgrade --install csi-driver-nfs csi-driver-nfs/csi-driver-nfs --namespace kube-system --version v4.  
9.0 -f values.yaml

升级版本要谨慎,新装版本要充分测试,特别是这种涉及数据安全的!

最后发现 sig 组还有一个 nfs-subdir-external-provisioner 可以看一下。

References