3. 每个脚本的详细信息及引用来源和参考资料

1 用Git备份方式建立Minecraft基岩版服务器
2 脚本列表
3 每个脚本的详细信息和引用来源·参考资料(即此处)

创建用户组
sudo adduser --system \
             --home $HOME_DIR \
             --shell $Login_Shell \
             --group \
             $New_USER
・--system:プログラム実行用アカウントとして構成する
・--home  :新規ユーザー用の作業ディレクトリを生成する
・--shell :ログインしたときに使うシェルを指定する
・--group :システム ユーザーと同じ名前と ID を持つグループを作成する
           (--systemと組み合わせない場合、ユーザーと同じ名前のグループを作成する)

参考来源:
Ubuntu 手册 [adduser, addgroup]
・https://manpages.ubuntu.com/manpages/trusty/man8/adduser.8.html
使用 Tailscale 运行私人 Minecraft 服务器
・https://tailscale.com/kb/1137/minecraft/

只需要一种选项 :

# 新規ユーザーのID、所属グループを表示
id $New_USER
# 特定のグループの所属メンバーを確認
getent group $New_GROUP
・uid=[user id]     :ユーザーのID(ユーザー名)を表す
・gid=[group id]    :メイングループGID(メイングループ名)を表す
・groups=[group id] :サブグループ名一覧(+GID)の表示

・user:x:gid:group  グループの所属メンバーを確認

以下为参考来源:
1. 【Linux命令集】id命令用于确认用户信息,详细说明请参考:https://eng-entrance.com/linux-command-id
2. 确认Linux组列表及/etc/group文件,请参考:https://kazmax.zpp.jp/linux_beginner/etc_group.html
3. 在Linux中,确认组内用户的命令,请参考:https://www-creators.com/archives/417

将Minecraft解压缩到<home目录>中。
# 作成したユーザーにログイン
sudo -i -u Minecraft

# サーバーのアーカイブをダウンロード、展開
DOWNLOAD_URL=$(curl -H "Accept-Encoding: identity" -H "Accept-Language: en" -s -L -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BEDROCK-UPDATER)" https://minecraft.net/en-us/download/server/bedrock/ |  grep -o 'https://minecraft.azureedge.net/bin-linux/[^"]*')
sudo wget $DOWNLOAD_URL -O /home/mcserver/minecraft_bedrock/bedrock-server.zip

在Ubuntu上设置Minecraft Bedrock服务器的来源是pimylifeup的教程,可以在以下网址找到:https://pimylifeup.com/ubuntu-minecraft-bedrock-server/#installing-the-minecraft-bedrock-server-on-ubuntu

创建设置文件和世界数据的备份目录。
sudo rm -r "/opt/MC_Manage"
sudo mkdir -p /opt/MC_Manage/{Properties,World_Backup}
sudo chown -R $New_USER:$New_GROUP "/opt/MC_Manage/"
sudo chmod -R 750 "/opt/MC_Manage/"
# 確認
sudo ls -laF "/opt/MC_Manage/"
・rm -r    :フォルダごと削除
・mkdir -p :親ディレクトリごと作成
・chown -R :$New_USERを所有者とし、$New_GROUPを所有グループとする
・chmod -R :所有者に完全なアクセス権(=750)を付与

以下是从以下引用和参考中得到的原始文本:
Linux命令【chown】:用于更改文件的所有者和组
– https://webkaru.net/linux/chown-command/
【Linux命令】chmod:设置权限的方法
– https://www.sejuku.net/blog/50161

这里是一个可能的汉语表述:
引用元·参考来源:
Linux命令【chown】可以用于更改文件的所有者和组。
– https://webkaru.net/linux/chown-command/
【Linux命令】chmod可以用来设置权限的方法。
– https://www.sejuku.net/blog/50161

<服务化,启动和停止脚本>
ExecStart=+/usr/bin/setpriv --reuid=$(/usr/bin/id -u minecraft) --regid=$(/usr/bin/id -g minecraft) --init-groups /opt/MC_Manage/start.sh
ExecStartPost=+/usr/bin/bash /opt/MC_Manage/backup.sh
ExecStop=+/usr/bin/setpriv --reuid=$(/usr/bin/id -u minecraft) --regid=$(/usr/bin/id -g minecraft) --init-groups /usr/bin/bash -c "/usr/bin/env XDG_RUNTIME_DIR=/run/user/$(/usr/bin/id -u minecraft) /usr/bin/systemctl --user stop nonstop_save.timer; exit 0"
ExecStop=+/usr/bin/setpriv --reuid=$(/usr/bin/id -u minecraft) --regid=$(/usr/bin/id -g minecraft) --init-groups /opt/MC_Manage/stop.sh
・Prefix:"+"
  実行パスの先頭に "+"が付いている場合、そのプロセスは完全な特権で実行されます。
  このモードでは、User=, Group=, CapabilityBoundingSet= や様々なファイルシステムの名前空間オプション (PrivateDevices=, PrivateTmp= など) で設定した特権制限は、起動したコマンドラインには適用されません (ただし、他の ExecStart=, ExecStop=, ... 行には影響があります)。
  しかし、DevicePolicy= のような、コントロールグループ全体に適用されるオプションはバイパスされないことに注意してください。
・setpriv --reuid "uid" --regid "gid" "--clear-groups/--groups/--keep-groups/--init-groups" --reset-env
    ・--reuid
        "uid" はユーザー名でも構いません。
    ・--regid
        "gid" はグループ名でも構いません。
    ・--clear-groups/--groups/--keep-groups/--init-groups
        グループを指定した場合には、いずれかが必要です。
    ・--reset-env
        各変数:HOME, SHELL, USER, LOGNAME, PATH=/usr/local/bin:/bin:/usr/bin を uid で指定したユーザーのものに初期化します。

使用Tailscale运行私人的Minecraft服务器
・https://tailscale.com/kb/1137/minecraft/
参考来源
Systemd入门(4) – service类型的Unit配置文件
・https://enakai00.hatenablog.com/entry/20130917/1379374797
systemd.service的man页面
・https://www.freedesktop.org/software/systemd/man/systemd.service.html
在systemd服务中调用shell时,应使用setpriv而不是sudo
・https://rheb.hatenablog.com/entry/setpriv
setpriv(1) — Linux手册页面
・https://man7.org/linux/man-pages/man1/setpriv.1.html

/usr/bin/tmux new-session -s minecraft -d
/usr/bin/tmux pipe-pane -t minecraft "cat >$Mine_DIR/Command.log"
/usr/bin/tmux send -t minecraft "LD_LIBRARY_PATH=$Mine_DIR ./bedrock_server | tee $Mine_DIR/Result.log" ENTER
・tmux new-session -s minecraft -d
    バックグラウンドで、minecraft と名前を付けたターミナルを起動します
・tmux pipe-pane -t minecraft "cat >$Mine_DIR/Command.log"
    ターミナルに表示されたものを丸ごとログファイルに出力
・tmux send -t minecraft "LD_LIBRARY_PATH=$Mine_DIR ./bedrock_server | tee $Mine_DIR/Result.log" ENTER
    Minecraft Server の実行結果をターミナルとログファイルに出力

使用Tailscale在自己的Minecraft服务器上运行
・https://tailscale.com/kb/1137/minecraft/
引用来源和参考资料
通过tmux保存日志
・https://seaoak.cocolog-nifty.com/read/2014/08/tmux-f687.html

/usr/bin/env XDG_RUNTIME_DIR=/run/user/$(/usr/bin/id -u minecraft) \
  /usr/bin/systemd-run \
    --on-active=${BK_INTERVAL} \
    --on-unit-active=${BK_INTERVAL} \
    --user \
    --collect \
    --unit=nonstop_save.service \
      /bin/bash -c "~~~~~~"
・--on-active
    タイマーが有効にされてからユニットを初めて実行するまでの時間
・--on-unit-active
    ユニットが最後に実行された時から次に実行されるまでの間隔
・--user
    root ではなく各ユーザー権限で実行する
・--collect
    正常に終了したか失敗したかにかかわらず、ユニットをアンロードします
・--unit
    既存のユニットが存在し、かつこの後にコマンドを入力しない場合は、指定したユニットが実行されます
    既存のユニットが存在せず、この後にコマンドを入力した場合は、指定したユニットの名前で入力したコマンドがサービス化されます

以下是原文的汉语翻译:

参考来源:
当用户权限的systemd连接失败时的解决方法
・https://blog.n-z.jp/blog/2020-06-02-systemd-user-bus.html
systemd-run
・https://www.freedesktop.org/software/systemd/man/systemd-run.html
使用systemd-run快速注册定期执行的任务
・https://qiita.com/ngyuki/items/a0404322e59f77cd512c

/usr/bin/tmux send -t minecraft stop ENTER
/usr/bin/tmux kill-session -t minecraft
・tmux send -t minecraft stop ENTER
    Minecraft Server に stop を送信します
・tmux kill-session -t minecraft
    tmux で起動した Minecraft 用のターミナルを終了します

使用Tailscale在私人Minecraft服务器上运行
– 链接:https://tailscale.com/kb/1137/minecraft

sudo loginctl enable-linger minecraft
・ログインしていないユーザーの長時間実行サービスを実行可能にする

引用来源和参考资料:
处理systemd中用户权限无法连接总线时的解决方法。
– https://blog.n-z.jp/blog/2020-06-02-systemd-user-bus.html
loginctl
– https://www.freedesktop.org/software/systemd/man/loginctl.html

function MC () {
  unset Arguments
  Arguments="${*//\"/\\\"}"
  Arguments="${Arguments:-exec bash}"
  sudo setpriv --reuid=$(/usr/bin/id -u minecraft) --regid=$(/usr/bin/id -g minecraft) --init-groups --reset-env bash --login -O expand_aliases -c "cd ~;IFS=' ' ${Arguments//\\\"/\"}"
}
・引数がない場合は ユーザー:minecraft でターミナルを起動する
・引数に含まれるエスケープされた二重引用符をさらにエスケープし、実行時にエスケープを外す
・bash --login -O expand_aliases
    ログインシェルとして起動し、/etc/profile, ~/.bash_profile, ~/.bash_login, ~/.profile を読み込む。終了時に ~/.bash_logout を読み込む。
    エイリアスの展開を行う

引用来源与参考文献为:
BASH
・https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html

<准备版本控制环境>
git init "~~~~~~"

cat << __EOF__ > "~~~~~~"
[user]
     name = Minecraft Server
    email = MinecraftServer@mydomain.com
__EOF__

git -C "~~~~~~" config --local gc.reflogExpire "never"
git -C "~~~~~~" config --local gc.reflogExpireUnreachable "3.days"
git -C "~~~~~~" config --local gc.pruneExpire "3.days.ago"

git -C "~~~~~~" commit --allow-empty --allow-empty-message -m ''
git -C "~~~~~~" commit --amend --allow-empty --allow-empty-message --no-edit

git -C "~~~~~~" reflog delete HEAD@{1} $(git -C "~~~~~~" branch --show-current)@{1}
・git init
   :git で管理できるようにディレクトリを初期化
・cat << __EOF__ > "~~~/.git/config"
    ⌇ ⌇ ⌇
 __EOF__ 
   :git commit に必要な情報を設定
・git commit --allow-empty --allow-empty-message -m ''
   :空コミット
・git commit --amend --allow-empty --allow-empty-message --no-edit
   :上書き空コミット
・git reflog delete HEAD@{1} $(git branch --show-current)@{1}
   :初回の空コミットを消す
_____________________________________
バックアップファイルの保存期限を設定
・git config --local gc.reflogExpire "never"
   :最新のバックアップは無期保存
・git config --local gc.reflogExpireUnreachable "3.days"
   :最新でなくなった後の保存期限
・git config --local gc.pruneExpire "3.days.ago"
   :最新でなくなった後の保存期限

引用来源及参考文献:
Git垃圾回收 (Git gc)
– https://www.atlassian.com/git/tutorials/git-gc

< 不需要停止服务器即可保存的脚本 >
function mc_save () {
  if [ "$(tmux ls -F '#{session_name}' -f '#{==:#{session_name},minecraft}' 2>/dev/null)" != "minecraft" ]; then
    git --git-dir="$Worlds_Bak_DIR/.git" \
        --work-tree="$Worlds_DIR" \
        add --intent-to-add -- :/
    git --git-dir="$Worlds_Bak_DIR/.git" \
        --work-tree="$Worlds_DIR" \
        diff --quiet --exit-code
    [ "$?" = "1" ] && backup_worlds 'Backup of stopped servers'
    # 新規ファイルか更新されたファイルがあった場合は、$?=1 を示す
    return 0
  fi

  /usr/bin/tmux send -t minecraft "save resume" ENTER
  /usr/bin/tmux send -t minecraft "save hold" ENTER

  EXITCODE=1 ; TRY_COUNT=0
  while [ "$EXITCODE" -ne "0" ]; do
   ((TRY_COUNT++))
    /usr/bin/tmux send -t minecraft "save query" ENTER
    sleep 1
    grep "Data saved. Files are now ready to be copied." <(tail -30 "$Mine_DIR/Result.log") > /dev/null 2>&1
    EXITCODE=$?
    if [ "$TRY_COUNT" -eq "20" ]; then break; fi
  done
}
・tmux ls -F '#{session_name}' -f '#{==:#{session_name},minecraft}'
    tmux に拠る minecraft のセッションが存在するか確認
・git add --intent-to-add
    blob オブジェクトは作成せず、インデックスに記入のみ行う
・diff --quiet --exit-code
    新規ファイルか更新されたファイルがあった場合は、$?=1 を返す
・[ "$?" = "1" ] && 
    $?=1 を返したときのみ後続のコマンドを実行する
・while ~~~ done
   Minecraft Server が "Data saved. Files are now ready to be copied." を返すまで "save query" を送信し続ける。最大20回まで。

脚本来源
mikenye/docker-minecraft_bedrock_server
・https://github.com/mikenye/docker-minecraft_bedrock_server/blob/main/rootfs/usr/local/bin/run_backup
引用来源・参考
处理格式
・https://github.com/tmux/tmux/wiki/Formats
tmux速查表
・https://qiita.com/nmrmsys/items/03f97f5eabec18a3a18b
使用Git进行判断文件更改是否包含创建新文件的方法
・https://reboooot.net/post/how-to-check-changes-with-git/
diff命令的退出代码是这样的,如果没有差异则为0,如果有差异则为1,失败则为2
・https://kinoppyd.dev/blog/diff-command-returns-1-but-success/

使用 Git 进行世界数据和设置文件的备份。
  git --git-dir="$Props_Bak_DIR/.git" \
      --work-tree="$Mine_DIR" \
      add -- permissions.json server.properties whitelist.json
  git -C "$Props_Bak_DIR" commit --amend --date=now --allow-empty-message -m ''"$@"
  git -C "$Props_Bak_DIR" --no-pager log --max-count=${1:-5} --reflog --format='%C(auto)%+h [%ad] %Cgreen%s' --name-only; echo ''
}
function backup_worlds () {
  SET_PATH="GIT_DIR=\"$Worlds_Bak_DIR/.git\" GIT_WORK_TREE=\"$Worlds_DIR\""
  while read READ; do 
    Args="$Args \"$READ\""
  done < <(eval $SET_PATH git ls-files --others --exclude-standard :/)
  eval $SET_PATH git add -- $Args >/dev/null 2>&1
  eval $SET_PATH git add --update
  eval $SET_PATH git update-index --remove --stdin < <(eval $SET_PATH git ls-files :/)
  git -C "$Worlds_Bak_DIR" commit --amend --date=now --allow-empty-message -m ''"$@"
}
function show_worlds_bak () {
  SKIP=0
  while read LINE; do
    git -C "$Worlds_Bak_DIR" log --max-count=1 --skip=$SKIP --reflog --format='%C(auto)%h [%ad] %Cgreen%s'
    git -C "$Worlds_Bak_DIR" ls-tree -d --name-only $LINE
    echo ''
   ((SKIP++))
  done < <(git -C "$Worlds_Bak_DIR" log --max-count=${1:-5} --reflog --format='%C(auto)%h')
}
・git add --update
   :リポジトリにある(追跡されている)更新されたすべてのファイルをステージに上げる
・git commit --date=now
   :今の日時を付けて情報を記録
・git log --max-count=n/-n --reflog --format='%C(auto)%h [%ad] %Cgreen%s'
   :コミットの履歴を表示する
   -n       :直近 n 件を表示(= --max-count=n )
   --reflog :git reflog で表示される操作の内、すべての git commit を列挙する
   --format
      %C(auto):次のみ自動で色付け
        green :以降すべて緑で表示
      %h      :オブジェクトを一意に指定するプレフィックスを表示
      [%ad]   :[日付] で表示
      %s      :コミット時のメッセージを表示
   --name-only
            :変更されたファイルの名前のみを表示
・git ls-tree -d --name-only <commit id>
   :ツリーオブジェクトの内容を一覧表示する
   -d       :サブディレクトリは表示せず、ツリーエントリのみ表示
   --name-only
            :ディレクトリ/ファイル名のみを 1 行に 1 つずつリスト

引用来源和参考链接如下:
Git – 文档
・https://git-scm.com/doc
・https://git-scm.com/docs/git-log
・https://git-scm.com/docs/git-ls-tree
获取内部文件列表的GIT ls-tree方法以及解决它们出现乱码的方法。
・https://blog.myntinc.com/2020/04/gitls-tree.html

<恢复用脚本>
    read Commit_ID < \
    <(git --git-dir="$Worlds_Bak_DIR/.git" \
          --work-tree="$Worlds_DIR" \
          for-each-ref \
            --sort=-committerdate \
            --count=1 \
            --format="%(objectname:short)" \
            refs/heads)
  backup_worlds
  git --git-dir="$Worlds_Bak_DIR/.git" \
      --work-tree="$Worlds_DIR" \
      restore --no-overlay --worktree --source=$Commit_ID -- "$2"
  mkdir -p "$Another_DIR"
  git -C "$Worlds_Bak_DIR" archive --format=tar $1 -- "$2" | tar Cx "$Another_DIR" --strip-components 1
・read Commit_ID < <(~~~~~~)
    :コマンド置換をして、その標準出力を変数に代入する
・for-each-ref \
    --sort=-committerdate --count=1 \
    --format="%(objectname:short)" refs/heads
    :refs/heads 以下にある各参照の内、最も最近コミットされたもののハッシュ値を取得する
・backup_worlds
    :バックアップ処理内で worlds 内のすべてのファイルをインデックスに記入する(追跡状態にする)
・git restore --no-overlay --worktree --source="commit id" -- world
    = git restore -WS -s "commit id" -- file
    :"backup_worlds" ですべてのファイルを追跡し、"git restore ~~~~~~ -- world" で指定したワールドを過去の状態に復元する
・mkdir -p "new world"
・git archive (--format=tar) world -- "new world" | tar Cx "new world" --strip-components 1
    :新しいワールドフォルダーを作成し、バックアップしたワールドデータをそこに復元する
    --format=tar         :既定
    --strip-components 1 :ディレクトリ構造の第一階層を無視する
    [C/--directory] DIR  :指定したディレクトリに展開する
    [x/--extract] ~.tar  :指定した tar ファイルを展開する
                           | を介して tar ファイル自体も受け取れる

参考来源:Git 官方文档(https://git-scm.com/doc)
如何在 BASH 中递归地只复制由 Git 版本控制的内容?
参考链接:Stack Overflow(https://stackoverflow.com/questions/44143371/in-bash-how-can-one-recursively-copy-only-content-version-controlled-by-git/44144020#44144020)

<删除备份的脚本>
  while read COUNT_HEAD; do 
    git -C "$Working_DIR" reflog delete "HEAD@{$SKIP}"
  done < <(git -C "$Working_DIR" --no-pager log --walk-reflogs --skip=$SKIP --format='%gd' HEAD)

  while read COUNT_MAIN; do 
    git -C "$Working_DIR" reflog delete "$(git -C "$Working_DIR" branch --show-current)@{$SKIP}"
  done < <(git -C "$Working_DIR" --no-pager log --walk-reflogs --skip=$SKIP --format='%gd' refs/heads/$(git -C "$Working_DIR" branch --show-current))

  git -C "$Working_DIR" gc --quiet
・while ~~~~~~ done
    :参照ログを、最新から "$SKIPに代入した数-1" まで残して、あとを消す
    :これを HEAD と refs/heads/~~~ 2つの参照ログで行う
・git gc --quiet
    :上記で残らなかった参照ログ及び, gc.reflogExpire, gc.reflogExpireUnreachable, gc.pruneExpire を元にして blob オブジェクトの削除を行う
    :ただし、参照ログに表示されているコミット+1までコミット本体が残る
    --quiet
    :ターミナル出力を抑制する

【引用/参考】
Git – 文档
· https://git-scm.com/doc
· https://git-scm.com/docs/git-reflog

广告
将在 10 秒后关闭
bannerAds