RockyLinux 9 使用usb硬碟備份,要避免硬碟進入休眠
過年要到了,小公司需要利用這時間進行系統備份,外接usb備份也很重要,備份完直接切斷usb硬碟連線,但我發現usb會進入休眠,不確定是否能終端機叫醒,因此乾脆直接改成不休眠狀態。
2013年有篇文章,有大佬分享心得

過年要到了,小公司需要利用這時間進行系統備份,外接usb備份也很重要,備份完直接切斷usb硬碟連線,但我發現usb會進入休眠,不確定是否能終端機叫醒,因此乾脆直接改成不休眠狀態。
2013年有篇文章,有大佬分享心得
慘,我的錯。
解決方式:
1. 到nextcloud該使用者目錄,找出<user>/files_trashbin/files 複製到 <user>/files
2. 執行 php occ files:scan –all
若出現 Exception during scan: “files/xxx”) is locked 則進入資料庫,刪除資料表資料 DELETE FROM oc_file_locks WHERE 1;
刪除之後,再次執行 php occ files:scan –all 還原檔案後,原本分享的狀態可能會不見,要自己重新設定了。
幾天前我想把nextcloud 25.0.11 升級到 26.0.5 ,這麼多年來從18版一路高歌升到25版,都沒遇到問題,這次卻栽了無法升級,原因卡在資料庫那段,這問題似乎無解,在不想等待的情況下,我決定還原回去。
2023/9/22 發現我25.0.11升級會出錯,官方馬上釋出25.0.12 ,但我升級還是失敗,原來資料庫mariadb 10.3.2版本有問題,我直接docker pull mariadb:10.3 後面不接了,這樣就從25->26能升級成功
還原步驟:
我先將restic 所備份最新版nextcloud備份的snapshot掛載起來,接著停用目前的資料庫(mariadb 10.3.2 多個容器共用);再將nextcloud的相關volume、資料庫還原,結果失敗,失敗原因不明,docker看log也看不出來,web登入出現「Nextcloud the server was unable to complete your request」錯誤,真真急死人;後來爬文,歸納問題可能有三種:目錄權限沒設定好、資料庫問題與ldap無法連線。
不屈不撓檢查才發現原來是我偷懶,當初所有容器所用到的資料庫都統一讓唯一的資料庫容器管理,現在要還原,我停止資料庫容器後,只有還原其中nextcloud的資料庫,其他資料庫不還原,導致重新啟動資料庫容器時,nextcloud資料庫居然有一些資料表損毀(ENGINE=InnoDB)。
好在損毀的資料表是oc_authtoken,只要重建就好了,但是重建失敗,mysql會說該資料表已在,但是query時,mysql又說沒有該資料表,網上有位苦命工程師說建資料表時,遇到這情形,請改用ENGINE=MyISAM格式就能成功,我照著做之後,nextcloud又恢復往日雄風還原成功,但重建的資料表MyISAM跟其他使用InnoDB的資料表格格不入,以後要找一天將資料庫修復才行。
這故事告訴我們,還原資料庫容器要全部都還原,不可只還原其中一部分資料庫。
CREATE TABLE `oc_authtoken` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `uid` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '', `login_name` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '', `password` longtext COLLATE utf8_bin, `name` longtext COLLATE utf8_bin NOT NULL, `token` varchar(200) COLLATE utf8_bin NOT NULL DEFAULT '', `type` smallint(5) unsigned NOT NULL DEFAULT '0', `remember` smallint(5) unsigned NOT NULL DEFAULT '0', `last_activity` int(10) unsigned NOT NULL DEFAULT '0', `last_check` int(10) unsigned NOT NULL DEFAULT '0', `scope` longtext COLLATE utf8_bin, `expires` int(10) unsigned DEFAULT NULL, `private_key` longtext COLLATE utf8_bin, `public_key` longtext COLLATE utf8_bin, `version` smallint(5) unsigned NOT NULL DEFAULT '1', `password_invalid` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `authtoken_token_index` (`token`), KEY `authtoken_last_activity_idx` (`last_activity`), KEY `authtoken_uid_index` (`uid`), KEY `authtoken_version_index` (`version`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
以上重建table失敗
CREATE TABLE `oc_authtoken` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `uid` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '', `login_name` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '', `password` longtext COLLATE utf8_bin, `name` longtext COLLATE utf8_bin NOT NULL, `token` varchar(200) COLLATE utf8_bin NOT NULL DEFAULT '', `type` smallint(5) unsigned NOT NULL DEFAULT '0', `remember` smallint(5) unsigned NOT NULL DEFAULT '0', `last_activity` int(10) unsigned NOT NULL DEFAULT '0', `last_check` int(10) unsigned NOT NULL DEFAULT '0', `scope` longtext COLLATE utf8_bin, `expires` int(10) unsigned DEFAULT NULL, `private_key` longtext COLLATE utf8_bin, `public_key` longtext COLLATE utf8_bin, `version` smallint(5) unsigned NOT NULL DEFAULT '1', `password_invalid` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `authtoken_token_index` (`token`), KEY `authtoken_last_activity_idx` (`last_activity`), KEY `authtoken_uid_index` (`uid`), KEY `authtoken_version_index` (`version`) ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
改成MyISAM就成功重建table
備份手法很多,最簡單就是整個主機定期做快照,加上離線備份,這樣就沒甚麼問題了。
但是我最近思考一件事,若我們想將podman上的容器軟體改成docker或是改回實體機使用, 這樣就比較棘手了。
我自己因為遇到podman storage要改不同位置,依照我以前文章更改storage路徑的做法再改一次路徑,podman居然整個崩潰了,搞到還要執行 podman system reset 才能恢復使用,但是reset後,原本的容器軟體全部出問題,若我有乖乖針對容器軟體進行備份,就不會這麼難堪了,最後只能整個VM還原。
所以我想了又想,覺得還是要直接備份容器的「images」與「volumes」。
爬文爬了幾天,修修改改後,我終於融合一個能備份容器以及其volume的腳本,很適合容器母體(host)為Linux使用,該腳本會備份所有的images、volume與執行容器指令。
按此下載podman容器備份腳本(需要輸入guest/guest,下載後請記得修改開頭幾行之備份路徑)。
執行備份,先備份images,然後掃描volume,查詢volume若與images互通款取,也一併備份,最後追蹤最初容器執行之指令,也一併圈禁備份起來。
備份後,每個目錄將包含容器使用之images、volumes與rush.sh(啟用指令)
後來我發現volume很適合restic增量備份方式,可以減少我這腳本full backup很耗空間的作法。
因此又改寫了一份針對volume能增量備份的腳本,兩種可以同時搭配使用,例如每個月一次full backup,剩下的定期每日或每周進行restic備份。
按此下載podman容器使用restic備份腳本(需要輸入guest/guest,下載後請記得修改開頭幾行之備份路徑)。
因為要減少備份snapshots數量, 因此執行forget + prune 瘦身指令
restic forget --keep-last 3 --prune -r <repository>
但是出現某某snapshots中有某些 pack missing 錯誤
some pack files are missing from the repository, getting their blobs from the repository index: [c3622b51e9c118521af211cd3a98f580f5902824b6b665e62d61061acedbe71d]
很慘, 於是只好找一下該 pack, 看看是哪些檔案不見
restic find --pack c3622b51e9c118521af211cd3a98f580f5902824b6b665e62d61061acedbe71d -r <repository>
最後終於找到某些snapshots遺失哪些檔案, 但依舊無法解決問題, 現主時只好忍痛直接將有問題的snapshots移除,等以後再研究解決方案
restic -r <repository> forget <snapshot id>
2023/2/8 後續
—
儘管forget該snapshots, 以為成功了.
但是再次執行備份,還是出現這個pack missing錯誤.
於是爬文, 發現必須先刪除相關packs , 再重跑以下步驟:
restic rebuild-index
restic backup –force
restic prune
詳細處理方式請查看 https://feeding.cloud.geek.nz/posts/removing-corrupted-data-pack-restic-backup/ 或是我下載好該網頁內容
oracle我很不熟, 但在公司使用exp指令備份oracle 11g資料時, 遇到以下錯誤訊息
EXP-00056: ORACLE error 1555 encountered
ORA-01555: snapshot too old: rollback segment number with name "" too small
ORA-22924: snapshot too old
爬了文, 解法有三, 我從最簡單的解法開始, 第一種,第二種都失敗, 直到第三種方式才成功.
我建議從第三種方式開始解,該方法不需修改系統設定, 影響較小.
SQL> show parameter undo;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 21600
undo_tablespace string UNDOTBS1
SQL> ALTER SYSTEM SET UNDO_RETENTION = 43200;
SQL>
System altered.
SQL>
# 新增undo tablespace
create undo tablespace UNDOTBS2 datafile '/.../oradata/undotbs02.dbf' size 30000M autoextend on next 100m maxsize unlimited;
#生效
alter system set undo_tablespace = UNDOTBS2 scope=both;
#查看狀態
select tablespace_name, status, count(*) from dba_rollback_segs group by tablespace_name, status;
select status,segment_name from dba_rollback_segs where status not in ('OFFLINE') and tablespace_name='UNDOTBS1';
select tablespace_name, status, count(*) from dba_rollback_segs group by tablespace_name, status;
#確認舊的已是offline , 就可以刪掉舊的
Drop tablespace UNDOTBS1 including contents and datafiles;
#再次查看是否已變成新的undo tablespace
show parameter undo
select tablespace_name tablespace, status, sum(bytes)/1024/1024 sum_in_mb, count(*) counts
from dba_undo_extents
group by tablespace_name, status order by 1,2;
# 先建立一個資料表, 用來儲存有問題的資料ID(ROWID)
SQL> CREATE TABLE CORRUPTED_ROWS (CORRUPTED_ROWID ROWID, ERROR_NUMBER NUMBER);
Table created.
接下來將有錯誤資料表table schema , 欄位類型為clob , blob 欄位列出來, 問題一定在這幾個欄位之中
# 以下紅色部分請改為有問題資料表與欄位名稱, 若沒有出現錯誤, 就換下一個欄位(fieldname)試試看
SET TIMING ON
DECLARE
ERROR_1578 EXCEPTION;
ERROR_1555 EXCEPTION;
ERROR_22922 EXCEPTION;
PRAGMA EXCEPTION_INIT(ERROR_1578, -1578);
PRAGMA EXCEPTION_INIT(ERROR_1555, -1555);
PRAGMA EXCEPTION_INIT(ERROR_22922, -22922);
N NUMBER;
BEGIN
FOR ROW IN (SELECT ROWID, fieldname FROM user.table)
LOOP
BEGIN
N:=DBMS_LOB.INSTR(ROW.fieldname, HEXTORAW('889911'));
EXCEPTION
WHEN ERROR_1578 THEN
INSERT INTO CORRUPTED_ROWS VALUES (ROW.ROWID, 1578);
COMMIT;
WHEN ERROR_1555 THEN
INSERT INTO CORRUPTED_ROWS VALUES (ROW.ROWID, 1555);
COMMIT;
WHEN ERROR_22922 THEN
INSERT INTO CORRUPTED_ROWS VALUES (ROW.ROWID, 22922);
COMMIT;
END;
END LOOP;
END;
/
接下來查詢是否真有問題資料
SELECT * FROM CORRUPTED_ROWS;
#執行以下這行指令應該要出錯
SELECT fieldname FROM user.table WHERE ROWID IN (SELECT CORRUPTED_ROWID FROM CORRUPTED_ROWS);
清空有問題的資料欄位
#若欄位型態是clob就用empty_clob(), 若為blob,就改成empty_blob(), 有幾個欄位出問題就清空幾個
update xxx.table set fieldname = empty_clob()where ROWID IN (SELECT CORRUPTED_ROWID FROM CORRUPTED_ROWS);
若不敢清空, 可以跳過有問題的資料備份
exp system@yourinstance BUFFER=81920 file=/tmp/backup.dmp tables=user.table QUERY=\"WHERE rowid NOT IN \(SELECT CORRUPTED_ROWID FROM CORRUPTED_ROWS\)\"
參考資料
我已經使用 restic 做離線備份半年了 , 效果還不錯, 但是遇到掛載nfs的資料, 效率就有點差了,
當然備份效率差的原因之一, 是我暴力備份docker or podman 裡面storage 資料, 那邊檔案超級多, 又是透過 nfs 方式備份, 就算restic 每次只做差異性, 還是很慢.
後來想想, 我的虛擬伺服器 proxmox ve 也有遇到掛載nfs效率問題, 解法就是使用soft link, 所以自己使用mount指令掛載nfs應該也是可以改用soft方式, 以下列出一些心得
mount -t cifs -o username=xxx,password=xxx,domain=yyy,ro,cache=loose ...
mount -t nfs -o ro,soft ...
#查看
nfsstat -m
前陣子發現restic備份的好處, 尤其拿來當離線備份.
IT同事進行離線備份時, 有意無意被老闆路過, 看到滿滿備份畫面咻咻跑來跑去, 充滿了儀式感.
老闆開心, IT同仁也有成就感.
restic指令備份, 不夠自動化, 為了讓IT同事做少少的工作, 又讓IT同事與其他路過的同事覺得好專業, 因此寫了簡單的restic backup script , 可以協助掛載來源目錄, 掛載後,進行restic備份.
檔案請到這裡下載, 下載後請看readme.md檔案
服務器端啟用nfs server
yum install nfs-utils
## 分享目錄
mkdir -p /mnt/docker
vi etc/exports
=================
#只讀ro, 10.192.130.4可使用
/mnt/docker 10.192.130.4(ro,sync,no_root_squash,no_all_squash)
#讀寫rw, 10.192.130.0/24網段可使用
/mnt/docker 10.192.130.0/24(rw,sync,no_root_squash,no_all_squash)
=================
#啟用
firewall-cmd --zone=public --add-service=nfs --permanent
## rockylinux
#firewall-cmd --add-service={nfs,nfs3,mountd,rpc-bind} --permanent
firewall-cmd --reload
systemctl enable nfs
systemctl start nfs
## rockylinux
#systemctl enable nfs-server rpcbind
#systemctl start nfs-server rpcbind
#查看狀態(windows,linux通用)
showmount -e localhost
用戶端(linux)
mount -t nfs <server ip>:/mnt/docker <本地要掛載的目錄>
或是
mount -t nfs4 <server ip>:/mnt/docker <本地要掛載的目錄>
用戶端(windows)
mount -o anon \\ip\mount_path z: