QA #297
未完了誤削除したチケットを復活したい(バックアップからのチケット復旧用スクリプト有)
0%
説明
[お知らせ] 11/5午後、redmine.tokyo第23回勉強会開催(無料、受付中、品川+Zoom+YouTubeLive) https://redmine-tokyo.connpass.com/event/261924/
■現象/要望¶
誤削除したチケットを復活したい
本件の解説動画(YouTube)
■解決策¶
■前提条件確認
誤削除の状況,環境は千差万別。
下記条件により、可能な対応は異なります。
1.削除したチケットの内容が不明/バックアップデータ有
2.チケット親子関係の使用有無
3.SCMとの連携要否
4.元の番号に復元する必要の有無
■保険&影響緩和策
DBダンプを定期的に自動作成しておくと、誤削除時のリカバリが容易になります。(保険)
テストサーバにリストアし、内容コピペで十分なケースが殆ど。
長期保存不要で上書き対応。
チケット削除権限は基本的にユーザに付与しない。却下などでCloseにする。
削除必要な場合はadmin作業。
■復旧手順1(RedmineのDB対応の場合)¶
チケットを復旧する
http://daily-postit.blogspot.jp/2012/12/blog-post.html
具体的な作業内容は↓
Redmineの誤って削除したチケットをバックアップから復活させた話
http://shrkw.hatenablog.com/entry/how_to_recover_redmine_issue
チケット誤削除時の復旧用SQL(上記のDB操作部分に相当)を作成しました。
https://redmine.tokyo/issues/297#note-13
テーブル間の関連などは、↓の「Redmineサーバ統合事例」を参照ください。(CM:-)
http://www.slideshare.net/y503unavailable/redmine-42182169
(要注意)チケットの親子関係を利用している場合は、lft,rgtの調整を行わないと、下記の様なトラブルを招く可能性があります。
http://dqn.sakusakutto.jp/2012/04/redmine.html
削除してしまったチケットを復活させる。
http://rms-099.hatenablog.jp/entry/20101231/1293736805
production.logの書込み内容を利用してチケット再作成
親子チケットの対応含む
■復旧手順2(RedmineのDBを弄りたくない&バックアップデータ有&SVN連携)¶
チケットを別途作成し、内容を設定します。
(バックアップ用データを見ながら or テストサーバにバックアップデータをリストアして内容確認しながらコピペ)
SVNのコミットメッセージを変更します。(refs #チケット番号を変更)
RedmineのDB修正も必要です。refs #番号の変更
changesets , changesets_issues , journals
■復旧手順3(RedmineのDBを弄りたくない&バックアップデータ有&SVN連携&admin操作削減)¶
・チケット再作成
・SVNの該当変更部分を一旦戻す。
・SVNに再度コミットする時に再作成したチケット番号と紐付ける。
■対応状況¶
作業事例はありますが、心して対応ください。
作業前のDBとレポジトリのフルバックアップは当然です。
SCMとの連携必要&元の番号に復元する必要が無ければ、
チケット新規作成&SVNコミットメッセージ変更を選択した方が安全かもしれません。
■補足¶
Redmine本家でも、誤削除の対応提案チケットが出ており、数十件の要望が出ています。希望者は+1しに行きましょう。。
Deleting an issue only marks it as being deleted
http://www.redmine.org/issues/1380
Soft delete of issues
http://www.redmine.org/issues/6666
現状ではシャドウコピー機能の無いWindowsファイルサーバですね。
(シャドウコピーがあれば、ユーザのリストア依頼は桁違いに減る)
ファイル
奈良 裕記 さんが約7年前に更新
■Redmineのチケット削除処理内容¶
ソースファイル/関連メソッド
destroyとdeleteで検索
app/helpers/issue_helper.rb
削除前の確認ダイアログ表示
def issues_destroy_confirmation_message
app/views/issues/_action_menu.html.erb
<%= link_to l(:button_delete), issue_path(@issue), :data => {:confirm => issues_destroy_confirmation_message(@issue)}, :method => :delete, :class => 'icon icon-del' if @issue.deletable? %>
app/views/context_menus/issues.html.erb
<li><%= context_menu_link l(:button_delete), issues_path(:ids => @issue_ids, :back_url => @back),
:method => :delete, :data => {:confirm => issues_destroy_confirmation_message(@issues)}, :class => 'icon-del', :disabled => @can[:delete] %></li>
app/controllers/issues_controller.rb
親子関係、作業時間の処理
def destroy
@issues.each do |issue|
begin
issue.reload.destroy
rescue ::ActiveRecord::RecordNotFound # raised by #reload if issue no longer exists
# nothing to do, issue was already deleted (eg. by a parent)
end
end
/app/models/issue.rb
alias :base_reload :reload
def reload(*args)
@workflow_rule_by_attribute = nil
@assignable_versions = nil
@relations = nil
@spent_hours = nil
@total_spent_hours = nil
@total_estimated_hours = nil
base_reload(*args)
end
after_destroy :update_parent_attributes
親チケットがある場合は進捗率を再計算
奈良 裕記 さんがほぼ4年前に更新
■Redmineチケット誤削除時の復旧用SQL作成(Mysql/MariaDB対応)¶
■機能¶
Redmineでチケットを誤削除した時に、誤削除前の環境から削除したチケットのSQL情報を出力するシェルスクリプトです。
(誤削除前のDBバックアップが無いと役に立ちません)
■前提条件¶
下記を全て満たした場合に、自己責任で利用してください。
適用後に正常に動作しなくなっても対応できません。
・Linux環境にて、mysql/mariadbでRedmineを運用していること。
動作環境にroot権限でアクセスできること。DBに直接アクセスできること。¶
・チケット誤削除前のデータで正常に動作するバックアップ環境があり、mysqldumpで直接アクセスできること。
(dailyでsqlのdumpを出力しておく事を推奨)¶
・本スクリプトの出力をリストア先の環境に適用する前に、リストア先環境でDBのフルバックアップを取得すること。(特に本番稼働環境の場合、利用者へのアクセス/更新停止連絡は必須)¶
・SQLの基本的な処理内容が理解できていること。¶
・誤削除したチケットのIDが判っていること。¶
■作業手順¶
・誤削除環境と同等のバックアップ環境を立ち上げ、誤削除前のDB内容を反映する。¶
(稼働環境と同等のRedmineの環境に、誤削除前のRedmineのDBダンプ内容を取り込んで起動させる)
実際には起動しなくとも良いが、内容確認のために、Redmine上で誤削除前のデータを参照出来る事を推奨
スクリプトのコピーと実行権限設定¶
バックアップ環境のワーク用フォルダに、本スクリプトをコピーする。
redmine_dump_issueno.sh
chmod +x で、実行権限を付ける。
作業用アカウントが、本フォルダ上に書き込める事が必要。
スクリプトファイルのDBアクセス権限設定¶
コピーしてきたスクリプトファイルを編集し、先頭の下記3つの行を実際の動作環境に合わせる。
database=redmine username=redmine password=pass-word1
実際の動作環境の設定値は、下記ファイルに記載されている。この内容を転記する。
但し、転記先のpasswordには、ダブルクオーテーションを含まないこと。
Redmineインストールパスの下、config/database.yml
(例: /var/lib/redmine/config/database.yml )
productionセクションの
database=redmine
username=redmine
password=pass-word1
スクリプト実行し、リストア用SQLファイルを作成する¶
誤削除したチケット番号を引数にしてスクリプトを実行する。
(以下は 1004 番のチケットを誤削除した場合)
./redmine_dump_issueno.sh 1004
当該チケットに関連するSQLのINSERT文のファイルが生成される。(INSERT_チケット番号.sql)
念のため、このSQLファイルの内容を確認する。
SQLのINSERT文が並んでいる筈。
指定した番号のチケット情報が存在した場合は、
そのINSERT_チケット番号.sqlのファイルとして生成し、ファイル名を表示する。
また、チケットに紐付けられた添付ファイル情報も表示される。
指定した番号のチケット情報が存在しなかった場合には、
その旨表示する。
チケット復活対象RedmineのDBフルバックアップを作成する。¶
誤動作時に復旧可能とするため、
mysqldump -u username -p%password% database > backup_redmine_日付日時.sql
sqlファイルが正常に生成されていることを確認する。
(バックアップが正常に生成できていない場合は、絶対に以下の作業を実施してはならない)
本番環境のRedmine上に、作成したSQLファイルを転送する。¶
作成したSQLファイルを、SCPなどで復活対象のRedmineに転送する。
本番環境のRedmine上で、転送したSQLファイルを実行する。DBのバックアップを必ず作成する。¶
mysql -u username -p%password% %database < 誤削除したチケット番号.sql
チケット親子関係の修復¶
チケットの親子関係を利用している場合は、階層構造を再構築する必要がある。
Redmineのインストールフォルダに移動し下記実行する。
RAILS_ENV=production rails runner 'Issue.rebuild_tree!'
systemctl restart httpd
添付ファイルを戻す。¶
チケットに紐付けられた添付ファイルが無かった場合は作業無し
添付ファイルが存在する場合は、バックアップサーバからコピーする。
Redmine3.4以降の場合、削除したチケットの添付ファイルが残っている場合がある。(正常動作)
この場合は、残っていた添付ファイルをそのまま利用して構わない。
/* Redmine3.4で追加された、ファイル単位の重複排除機能が原因と思われる。
https://www.redmine.org/issues/25215
*/
attachmentsテーブル
2020/05/16なら、
2005/16時分..ファイル名となる。
MariaDB [redmine]> select disk_filename from attachments where container_id=61295; +-----------------------------------------------+ | disk_filename | +-----------------------------------------------+ | 200127231549_clipboard-202001272315-xfzke.png | +-----------------------------------------------+ 1 row in set (0.000 sec) # ls -al /var/lib/redmine/files/2020/01 -rw-r--r-- 1 apache apache 70663 Jan 27 23:15 200127231549_clipboard-202001272315-xfzke.png