tag:crieit.net,2005:https://crieit.net/tags/var/feed 「var」の記事 - Crieit Crieitでタグ「var」に投稿された最近の記事 2021-06-15T00:26:03+09:00 https://crieit.net/tags/var/feed tag:crieit.net,2005:PublicArticle/17404 2021-06-15T00:24:38+09:00 2021-06-15T00:26:03+09:00 https://crieit.net/posts/var 大事なサーバの/varを消した話。悪夢の無限列車編👹 <p>お久しぶりです!<br /> ここの所、立て込んでいたり(表題の件で)、メンタルやられ気味だったり(表題の件で)で余裕がなかった私です。</p> <p>あれほど講師の方に、「<strong>rmを使うときは気を付けよう</strong>」と言われていたのに…</p> <hr /> <h4 id="v目次にゃv"><a href="#v%E7%9B%AE%E6%AC%A1%E3%81%AB%E3%82%83v">v目次にゃv</a></h4> <p>1.どんなサーバなのか<br /> 2.CentOSの/varを消したお話ー悪夢の始まり無限列車編<br /> 3.CentOSの/varを消したお話ー血鬼術の落とし穴編<br /> 4.消した後ーお前ももうおやすみ・・・<br /> 5.起こったこと<br /> 6.復旧作業<br /> 7.結末<br /> 8.考えられる復元法<br /> 9.回避の呼吸!型集</p> <hr /> <h4 id="どんなサーバなのか"><a href="#%E3%81%A9%E3%82%93%E3%81%AA%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AA%E3%81%AE%E3%81%8B">どんなサーバなのか</a></h4> <p>私はゲーム制作サークルのサーバ担当(仮?)をしてますねこー。<br /> ざっくり挙げると<br /> ・ホームページ<br /> ・工程、プロジェクト管理ソフトの管理<br /> ・Gitサーバ<br /> を管理をしているきんぎょ。<br /> 昔はメールサーバもやっていたけど色々考えて、Google Workspaceと兼用させてるぎょぴ。</p> <p>ちなみに、VPSでCentOS7をつかっていますきんぎょ。<br /> <strong>これは消してはいけない。障害を起こしてはダメなやつだ()</strong></p> <hr /> <h4 id="CentOSの/varを消したお話ー悪夢の始まり無限列車編"><a href="#CentOS%E3%81%AE%2Fvar%E3%82%92%E6%B6%88%E3%81%97%E3%81%9F%E3%81%8A%E8%A9%B1%E3%83%BC%E6%82%AA%E5%A4%A2%E3%81%AE%E5%A7%8B%E3%81%BE%E3%82%8A%E7%84%A1%E9%99%90%E5%88%97%E8%BB%8A%E7%B7%A8">CentOSの/varを消したお話ー悪夢の始まり無限列車編</a></h4> <p>今回、新しいシステムの導入にあたって、色々入れたり、消したりをしていたねこ~。<br /> とある理由から<br /> /var/hogehoge/nekoneko/<br /> /var/hogehoge/kitune/<br /> /var/piyopiyo/fugafuga/<br /> のkingyo.poi を×10個くらい(仮称)を消す必要があったにゃ。<br /> そこで下記のコマンドを実行し、対象ファイルを削除していきました。</p> <pre><code>rm -rf /var/hogehoge/#抹消対象# </code></pre> <p><strong>そう。これが悪夢の始まりだったのにゃー…</strong></p> <hr /> <h4 id="CentOSの/varを消したお話ー血鬼術の落とし穴編"><a href="#CentOS%E3%81%AE%2Fvar%E3%82%92%E6%B6%88%E3%81%97%E3%81%9F%E3%81%8A%E8%A9%B1%E3%83%BC%E8%A1%80%E9%AC%BC%E8%A1%93%E3%81%AE%E8%90%BD%E3%81%A8%E3%81%97%E7%A9%B4%E7%B7%A8">CentOSの/varを消したお話ー血鬼術の落とし穴編</a></h4> <p>先ほど紹介した<strong><em>rm -rf /var/hogehoge/#抹消対象#</em></strong> の血鬼術ですが、重大な"<strong>欠陥</strong>"がある鬼~。<br /> そう、"<strong>血</strong>"鬼術だけに…(欠陥と血管をかけた)</p> <p>基本的にLinuxにはWindowsでいう<strong>ゴミ箱</strong>が存在しないきんぎょ。<br /> つまり、消したものは、ほぼ<strong>二度と元には戻りません</strong>。</p> <h5 id="今回の落とし穴(後悔ポイント)"><a href="#%E4%BB%8A%E5%9B%9E%E3%81%AE%E8%90%BD%E3%81%A8%E3%81%97%E7%A9%B4%EF%BC%88%E5%BE%8C%E6%82%94%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%EF%BC%89">今回の落とし穴(後悔ポイント)</a></h5> <p><strong>・cdで/varに移動して作業していれば消えるフォルダは最小で済んだ<br /> ・脳死でポチポチやっていた<br /> ・脳死のためエンターキーとTabキーを間違えた</strong></p> <p>抹殺対象を消すために、1つ1つ手打ちで打っていたわけです。正規表現しようにも、ダブりで消せないファイルもあるので…<br /> 数もそれなりにあるので、脳死状態でポチポチ術を発動していきます。Tab変換を活用して…</p> <p><strong>rm -rf /var エンターキーポチッ!</strong>\(^o^)/アッオワッタ<br /> 実行した瞬間、理解できず、思考がグルグル走馬灯。一瞬が5分くらいに長く感じ、冷や汗が全身をつたいました。</p> <hr /> <h4 id="消した後ーお前ももうおやすみ・・・"><a href="#%E6%B6%88%E3%81%97%E3%81%9F%E5%BE%8C%E3%83%BC%E3%81%8A%E5%89%8D%E3%82%82%E3%82%82%E3%81%86%E3%81%8A%E3%82%84%E3%81%99%E3%81%BF%E3%83%BB%E3%83%BB%E3%83%BB">消した後ーお前ももうおやすみ・・・</a></h4> <p>/varを消した直後、<br /> ”今動いているシステムは消せないよ”とのメッセージが。<br /> lsで確認すると<strong>tmp以外消えている!!!!!!!!!</strong><br /> 【VirtualBoxで再現した写真↓もちろん今回はバックアップをとってある】<br /> <a href="https://crieit.now.sh/upload_images/c8e3813e38831a16492d64162853d8f060c75922bdfa5.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/c8e3813e38831a16492d64162853d8f060c75922bdfa5.png?mw=700" alt="image.png" /></a>!</p> <hr /> <h4 id="起こったこと"><a href="#%E8%B5%B7%E3%81%93%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8">起こったこと</a></h4> <p>・/varに配置しているものは<strong>全て消失</strong>しました。<br /> →ホームページの消失<br /> →行程、プロジェクト管理のデータ消失(Webで動作するもののため)<br /> →プロジェクト管理のデータベース消失<br /> ・yumが死んだ。(rpmもだめ)<br /> ・firewallが起動できない(iptablesはギリ生きていたっぽい?)<br /> ・SSHアクセスが弾かれる<br /> ・私は内心大泣き<br /> ・私、汗だく</p> <p>・gitも死んだと思っていたら、/var以外の場所で管理していたのでセーフ(本当に良かった。)<br /> ・wgetやcurlは使用可能</p> <hr /> <h4 id="復旧作業"><a href="#%E5%BE%A9%E6%97%A7%E4%BD%9C%E6%A5%AD">復旧作業</a></h4> <p>どうやら<strong>extundeleteコマンド</strong>で復旧可能らしい!<br /> 標準では入っていないので、<strong>yum install extundeleteで導入</strong>します!<br /> <strong>_人人人人人人人人人人人_<br /> > yumが使えない!! <<br />  ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄</strong><br /> はい。終わりました。<br /> どうやら<strong>yumにかかわるデータが/var以下</strong>にあったようで、<strong>正常に動作しなくなりました</strong>。</p> <p>他にデータ復元方法はいくつかあり、試しましたが全部だめでした。<br /> 他のcentから消えたデータを移植したり、リカバリーモードを起動したり、OSの書き換えを試みたり…</p> <hr /> <h4 id="結末"><a href="#%E7%B5%90%E6%9C%AB">結末</a></h4> <p>結局、新しくサーバを立て、生きているデータを故サーバからサルベージ。移行する手段を取りました。<br /> VPSという特性上いろいろ気を遣う作業が多かったです。(今回ばかりはハードを直で触れる自宅サーバを羨みました。)</p> <hr /> <h4 id="考えられる復元法"><a href="#%E8%80%83%E3%81%88%E3%82%89%E3%82%8C%E3%82%8B%E5%BE%A9%E5%85%83%E6%B3%95">考えられる復元法</a></h4> <p>私の知識、経験不足ゆえに、実現しませんでしたが、この状況でも復活できる可能性はありました。<br /> ・wgetやcurlを使って修復系パッケージの導入<br /> ・健全なサーバより消滅したデータを移行。権限や依存関係も手動で設定<br /> ・パーティションやプロセスから復元<br /> いずれも果てしない労力と戦場で培うべき経験、正しい知識が必要なためペーペーの私は力尽きました…</p> <hr /> <h4 id="回避の呼吸!型集"><a href="#%E5%9B%9E%E9%81%BF%E3%81%AE%E5%91%BC%E5%90%B8%EF%BC%81%E5%9E%8B%E9%9B%86">回避の呼吸!型集</a></h4> <p><strong>今から大事なことを書きます!</strong><br /> <strong>・rmコマンドの扱い</strong><br /> まずはrmコマンドを使うときは慎重に行きましょう。絶対です。<br /> 特に-rf オプションを使うときは<strong>要注意</strong>です。なんでも消せちゃいます。イレイザーヘッドです💦<br /> <strong>・バックアップを取っておく</strong><br /> 何事も作業前にバックアップを取っておきましょう。VirtualBoxならスナップショット。VPSならイメージOSの保存とかね。<br /> <strong>・extundelete等の復元ツールは予め入れておく</strong><br /> ことが起きてからでは遅いです。今回みたくyumひいてはOSそのものがダウンして緊急時には何が使えなくなるか分かりません。前もって対策しておきましょう。<br /> <strong>・実験環境を用意、活用する</strong><br /> 普通なら本番と全く同じ実験環境(兼バックアップ)を利用すべきです。コストがかかるのは仕方ないですが、<strong>データ復旧費や今までの労力が水の泡になるよりは安い</strong>です!<br /> サークル活動でのリアルな実験環境費用捻出は難しいですが…<br /> 本当に業務上じゃなくてよかった…<br /> <strong>・ある程度子ディレクトリに入って作業をする</strong><br /> 今回は絶対パスで/varと打っていたのも原因の1つです。<br /> 仮にvarにい状態で作業していれば<strong>varそのものが消えるという事態は避けられていました</strong>。</p> <hr /> <h4 id="エンドタイトル"><a href="#%E3%82%A8%E3%83%B3%E3%83%89%E3%82%BF%E3%82%A4%E3%83%88%E3%83%AB">エンドタイトル</a></h4> <p>ということで悪夢の無限列車編を締めくくりたいと思います。<br /> <strong>何かあってからでの対策では遅い</strong>ということを痛感しました。<br /> 色々やばすぎて、語尾を忘れるくらいですからきんぎょ。<br /> 本当に業務での失態でなくてよかったです…おそらく私じゃ払いきれない額の損害でしょうから(震え)<br /> さらに辛かったのが「<strong>var消しちゃった</strong>💦」で検索しても<strong>ヒットしなかった</strong>ことです。varを消す馬鹿野郎は私くらいということですかね~(すっとぼけ)</p> <p>今回はここまで🐾<br /> みなさん、私の屍を超えていけ!!!!</p> keito_woood tag:crieit.net,2005:PublicArticle/16547 2021-01-06T20:08:06+09:00 2021-01-06T20:09:22+09:00 https://crieit.net/posts/csharp-var 【C#】varの使い方、メリットとデメリット <h1 id="使い方"><a href="#%E4%BD%BF%E3%81%84%E6%96%B9">使い方</a></h1> <p>C#では変数宣言時、型を書く必要がある。</p> <pre><code class="csharp">string text = "あいうえお"; </code></pre> <p>この時、<code>var</code>キーワードを使用することで右辺から型を推論させて変数宣言を行える。</p> <pre><code class="csharp">var text = "あいうえお"; // textはstring型となる </code></pre> <p>Visual Studioで確認すると、<code>string</code>型となっていることがわかる。<br /> <a href="https://crieit.now.sh/upload_images/e84f7ee882c4fb25f5501a6ff08accd65ff59a5ca7382.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/e84f7ee882c4fb25f5501a6ff08accd65ff59a5ca7382.jpg?mw=700" alt="image" /></a></p> <p><code>var</code>は右辺から型を判別している。そのため、下記のコードはコンパイルエラーとなる。</p> <pre><code class="csharp">var text = null; // nullの型を判別できないためコンパイルエラーとなる </code></pre> <p>もし<code>string</code>型の<code>null</code>を<code>var</code>を使って宣言する場合、下記のように書かなければならない。</p> <pre><code class="csharp">var text = (string)null; </code></pre> <p>この記法だと一応宣言はできるが、あまり型推論のメリットがない。(後述するようにメリットがない訳ではない)</p> <h1 id="メリット"><a href="#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88">メリット</a></h1> <p><code>var</code>を使うと次のメリットがある。</p> <ul> <li>複雑な型名を書かなくても良い</li> <li>型が変更されたときに書き直さなくても良い</li> <li>コードが読みやすくなる</li> </ul> <p>順番に解説する。</p> <h2 id="複雑な型名を書かなくても良い"><a href="#%E8%A4%87%E9%9B%91%E3%81%AA%E5%9E%8B%E5%90%8D%E3%82%92%E6%9B%B8%E3%81%8B%E3%81%AA%E3%81%8F%E3%81%A6%E3%82%82%E8%89%AF%E3%81%84">複雑な型名を書かなくても良い</a></h2> <p>たとえば<code>Dictionary<Dictionary<Dictionary<int, string>, string>, Dictionary<Dictionary<int, string>, Dictionary<int, string>>></code>を返す<code>NegativeMethod</code>という関数があるとしよう。</p> <p>これも<code>var</code>を使うと型名を書かなくてよい。</p> <pre><code class="csharp">public static Dictionary<Dictionary<Dictionary<int, string>, string>, Dictionary<Dictionary<int, string>, Dictionary<int, string>>> NegativeMethod() { Dictionary<Dictionary<Dictionary<int, string>, string>, Dictionary<Dictionary<int, string>, Dictionary<int, string>>> something = new Dictionary<Dictionary<Dictionary<int, string>, string>, Dictionary<Dictionary<int, string>, Dictionary<int, string>>>(); // ~複雑な処理 return something; } Dictionary<Dictionary<Dictionary<int, string>, string>, Dictionary<Dictionary<int, string>, Dictionary<int, string>>> result = NegativeMethod(); </code></pre> <p>上記のようなコードが、下記のように書ける。</p> <pre><code class="csharp">public static Dictionary<Dictionary<Dictionary<int, string>, string>, Dictionary<Dictionary<int, string>, Dictionary<int, string>>> NegativeMethod() { var something = new Dictionary<Dictionary<Dictionary<int, string>, string>, Dictionary<Dictionary<int, string>, Dictionary<int, string>>>(); // ~複雑な処理 return something; } var result = NegativeMethod(); </code></pre> <p>型が明確になっている場合は、複雑な型を書かなくて良くなる。<code>Tuple</code>や<code>Dictionary</code>は複雑になる場合もあるが、それをいちいち書かなくても良いメリットとなる。なお、後述するがこういう使い方にはデメリットもあるので注意。</p> <h2 id="型が変更されたときに書き直さなくても良い"><a href="#%E5%9E%8B%E3%81%8C%E5%A4%89%E6%9B%B4%E3%81%95%E3%82%8C%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AB%E6%9B%B8%E3%81%8D%E7%9B%B4%E3%81%95%E3%81%AA%E3%81%8F%E3%81%A6%E3%82%82%E8%89%AF%E3%81%84">型が変更されたときに書き直さなくても良い</a></h2> <p>たとえば<code>userId</code>は<code>int</code>型だったが、アルファベットを含めるという仕様変更にあたり<code>string</code>型に変更することになったとする。</p> <p>ここで、下記のように修正する必要がある。</p> <pre><code class="csharp">// GenerateUserIdはintを返す int userId = GenerateUserId(); // ▲これを下記のように変更する▼ // GenerateUserIdはstringを返すようになった string userId = GenerateUserId(); </code></pre> <p>数か所であれば問題ないがもし何十箇所・何百箇所も記載してあればそれらを漏れなく修正する必要がある。</p> <p>一括で置換するという方法もない訳ではないが、対象が漏れなく置換されたか、本来修正範囲外のコードが変更されていないかなどの差分確認の作業が結局発生する。</p> <p>初めから<code>var</code>で記載しておけば型が変更されてもコードの修正が必要なく、修正後にテストを走らせればそれだけで済む。</p> <pre><code class="csharp">// GenerateUserIdがintからstringになっても、ここは修正する必要がない var userId = GenerateUserId(); </code></pre> <h2 id="コードが読みやすくなる"><a href="#%E3%82%B3%E3%83%BC%E3%83%89%E3%81%8C%E8%AA%AD%E3%81%BF%E3%82%84%E3%81%99%E3%81%8F%E3%81%AA%E3%82%8B">コードが読みやすくなる</a></h2> <p>ここは感覚的な問題だが例を示す。</p> <p>下記のようなコードがあるとする。</p> <pre><code class="csharp">int userId = GenerateUserId(); string firstName = ""; string lastName = ""; DateTime birthday = new DateTime(1990, 1, 1); </code></pre> <p>これは<code>var</code>を使用すると次のように書ける。</p> <pre><code class="csharp">var userId = GenerateUserId(); var firstName = ""; var lastName = ""; var birthday = new DateTime(1990, 1, 1); </code></pre> <p>こうすると型の部分が全て<code>var</code>になり、変数名のインデントが揃って読みやすくなる…気がする。少なくとも私は、バラバラに型を書いているより<code>var</code>で揃っていた方が読みやすい。</p> <h1 id="デメリット"><a href="#%E3%83%87%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88">デメリット</a></h1> <p>上記のようにとてもメリットの大きな<code>var</code>だが、デメリットとなるケースも存在する。</p> <p>それは、人間が容易に型を推論できない場合だ。</p> <pre><code class="csharp">var firstName = GetFirstName(userId); </code></pre> <p>上記の場合、おそらく<code>firstName</code>は<code>string</code>型になるだろうという想像が出来る。<code>var</code>を使用するのが相応しいケースの一つだ。</p> <p>しかし下記の場合はどうだろう?</p> <pre><code class="csharp">var idAndNames = GetIdAndNames(); </code></pre> <p><code>GetIdAndNames</code>はおそらく<code>id</code>と<code>name</code>を(おそらくペアで)取得するメソッドだと予想はできるが、どういう型になっているかは実装部分を見ないと判定できない。<code>Dictionary<int, string></code>かもしれないし<code>List<Tuple<int, string>></code>かもしれない。独自クラスのコレクションになっている可能性もある。</p> <p><code>var</code>を使用したら<code>GetIdAndNames</code>がどのような型を返すとしても寛容に受け入れてしまう反面、型が分かりにくくなるというデメリットもある。(上記の例は関数名などのネーミングの問題もあるが)</p> <p>Visual StudioなどのIDE上で読むのであれば、変数名にマウスオーバーしたら型が分かるが、バージョン管理ソフトの履歴などの画面では当然そのような機能がないため読みづらい。型が分かりにくい場合は型を明記するが、コメントを添えておくと良いだろう。</p> <p>コメントは後で型が変わった時などにメンテしなければならないので、明記する方が個人的には良いと思う。型を明記していればコンパイルエラーなどで検知できるので修正漏れを防ぐ助けにもなる。</p> <pre><code class="csharp">// varを使わず型を明記する場合 Dictionary<int, string> = GetIdAndNames(); // コメントを添える場合 // GetIdAndNamesはDictionary<int, string> var idAndNames = GetIdAndNames(); </code></pre> <h1><code>var</code>は使うべきか</h1> <p>これはもちろんチームのコーディング規約や方針に従わなければならないが、少なくとも私は個人開発では積極的に利用する。私がアサインされたチームでも今のところ「<code>var</code>は禁止」というところはなかったので非常に助かっている。</p> <p>Microsoftの<a target="_blank" rel="nofollow noopener" href="https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/inside-a-program/coding-conventions">C# のコーディング規則 (C# プログラミング ガイド)</a>にも、</p> <blockquote> <p>変数の型が割り当ての右側から明らかである場合、または厳密な型が重要でない場合は、ローカル変数の暗黙の型指定を使用します。</p> </blockquote> <p>と明記されている。</p> あぱしょに