vim で 読み取り専用ファイルを強制保存する

1. sudo で開いた場合

1) sudo vim filename
2) 編集する
3) :wq

2. sudo なしで開いた場合編集→コマンドモードで強制保存

1) vim filename
2) 編集する
3) :w !sudo tee %

  • w: 内容を保存する
  • !sudo tee: 「:w」の内容を「!sudo tee」で受け取ることができる
    • !: 「!」をつけるとVim エディタで Linuxコマンドが実行できるようになる
    • sudo: 管理者権限で実行する
    • tee: ファイルの出力と標準出力を同時に行うコマンド。sudo と組み合わせるとファイルを上書き保存する
  • %: 現在のファイル名を指定する

4) q!

SSH接続でタイムアウトによる自動切断を防ぐ

サーバー:さくらVPSサーバー(Debian 10.6)
クライアント:macOS catalina 10.15.7

Macで一定期間何もせずにいると、タイムアウトにより、さくらVPSサーバーへのSSH接続が自動的に切断されます。
これを防ぐための覚書です。

1. クライアント側の設定

sshd サーバと応答確認する間隔 ServerAliveInterval を設定する。
ServerAliveInterval のデフォルト値は0で、デフォルトでは応答確認しないようになっている。

~/.ssh/config または /etc/ssh/ssh_config に
ServerAliveInterval 60

設定した60秒ごとにサーバにメッセージを送り応答がないと、ServerAliveCountMax の回数(デフォルト値: 3)まで繰り返す。
サーバが応答しなくなった180秒後にタイムアウトする。

2. サーバ側の設定

sshd サーバ側でも同じ設定をすることができる。

/etc/ssh/sshd_config に
ClientAliveInterval 60

Rubyの二次元配列

これは「フィヨルドブートキャンプ Part 1 Advent Calendar 2020」の7日目の記事です。

adventar.org

昨日は、Sakiさんの 「初めて輪読会をやってみたらいいことばかりだったので、良かったことをまとめました 」でした。
Part. 2 もあります。

adventar.org

私はWebエンジニアに転職したいと思い、現在フィヨルドブートキャンプで学んでいます。

bootcamp.fjord.jp

そのフィヨルドブートキャンプで、Advent Calendarの企画が立ち上がりました。
私はAdvent Calendarに参加するのは初めてなのですが、アウトプットを現在意識しているため書いてみることにしました。

とはいえ、Rubyのプラクティスに入ったばかりで何を書いたらいいのか迷いました。
先日、Unixのcalコマンド(カレンダー表示)をRubyで実装するプラクティスを行った際に、Rubyにおける二次元配列について少し調べたので、そのことを書くことにしました。
カレンダーつながりですね!☺️
Ruby初心者ですので、暖かい目で読んでいただけると助かります。

一次元配列

まず、一次元配列から考えます。
(参考:「スラスラ読める Rubyふりがなプログラミング」「ゼロからわかる Ruby 超入門」)

配列は要素として複数のオブジェクトをまとめて扱うクラスです。
オブジェクトとして、数値や文字列を扱います。
そして、配列自身もまた、オブジェクトです。
オブジェクトの種類のことをクラスと言います。

作成

配列を作成します。
wdays = ["月", "火", "水", "木", "金", "土", "日"]

要素を取得する

配列内の要素を取得する時は、インデックス(添え字)を使います。
puts wdays[2]
とすると
f:id:keikosmile:20201206073346p:plain
と表示されます。

配列全体を表示する時は、
puts wdays
とすると、
f:id:keikosmile:20201206074720p:plain
と各要素が縦に表示されます。

要素書き換え

配列の要素を書き換える時は、
wdays[1] = "雨"
puts wdays
とすると
f:id:keikosmile:20201206103907p:plain
と配列の要素が変わっています。

その他のメソッド

配列はArrayというクラスの一つで、元々色々便利なメソッドが備わっています。
(参考 Ruby 2.7.0 リファレンスマニュアル>ライブラリ一覧>組み込みライブラリ>Arrayクラス)

Arrayクラスの主なメソッド

メソッド 働き
配列.first 配列の最初の要素を返す
配列.last 配列の最後の要素を返す
配列.push(要素) 配列の末尾に要素を追加する
配列.unshift(要素 配列の先頭に要素を追加する
配列.delete(値) 配列から値と一致する要素を全て削除する
配列.shift 配列の先頭から要素を1つ削除し、削除した要素を返す
配列.pop 配列の末尾から要素を1つ削除し、削除した要素を返す
配列1 + 配列2 2つの配列の要素をつなげた配列を作る
配列1 - 配列2 配列1から配列2の要素を削除した新しい配列を作る
配列.size 配列の要素数を返す
配列.sum 配列の全要素の合計を返す
配列.sample 配列からランダムに要素を取得する
配列.shuffle 配列をランダムに並び換える
配列.sort 配列の要素を順に並び換える(数値:小さい順、文字列:abc順)
配列.sort.reverse 配列の要素の並びが逆順になる(数値:大きい順、文字列:cba順)
配列.join 配列中の文字列を連結する

初めから色々揃っていて便利ですね!

例1:deleteメソッド

例えば、deleteメソッドを使ってみます。
wdays.delete("雨")
puts wdays
f:id:keikosmile:20201206111331p:plain
"雨"が消えています!

例2:revereseメソッド

reverseメソッドがややこしかったので詳しく書きますと、
① 要素が数値の場合
p [4, 2, 8].sort

f:id:keikosmile:20201206165224p:plain
p [4, 2, 8].sort.reverse

f:id:keikosmile:20201206165435p:plain
p[4, 2, 8].reverse

f:id:keikosmile:20201206165558p:plain
reverseだけだと、先頭だけ逆順になり、全体はうまく並ばないので注意が必要です。
reverseだと、ただひっくり返った逆順になります。
(指摘していただき訂正しました!  2020.12.08)

② 要素が文字列の場合
p ["midori", "aka", "kiiro"].sort
f:id:keikosmile:20201206183858p:plain

p ["midori", "aka", "kiiro"].sort.reverse
f:id:keikosmile:20201206184010p:plain

p["midori", "aka", "kiiro"].reverse
f:id:keikosmile:20201206184126p:plain
reverseだけだと、同様に、先頭だけ逆順になり、全体はうまく並ばないので注意が必要です。
reverseだと、同様に、ただひっくり返った逆順になります。
(指摘していただき訂正しました! 2020.12.08)

例3:joinメソッド

joinメソッドは、配列の各要素をつなげるだけでなく、つなげるときに間へ入れる文字を指定できます。
puts ["空", "海", "太陽"].join("と")
f:id:keikosmile:20201206213444p:plain

二次元配列

配列は複数のオブジェクトを要素として扱うことができる。
配列自身もまたオブジェクトである。
それなら、配列の中で配列を要素として持てるはず…。

ということで、Rubyでは二次元配列も可能になっています。


しかし、どうやって作ればいいのだろう…。
calendar = [["1月1日", "1月2日", "1月3日"], ["2月1日", "2月2日", "2月3日"], ["3月1日", "3月2日", "3月3日"]]
とすれば初期化された二次元配列を作成することができ、

puts calendar[0][2]
puts calendar[2][1]
f:id:keikosmile:20201206220648p:plain
とすれば、各要素を表示することがわかりました。


でも、宣言はどうやってするのだろう...?
色々調べた結果、配列の宣言と初期化はnewメソッドを使えばできるようです。
calendar = Array.new(3, " 月 日")
calendar[2] = "2月1日"
puts calendar
f:id:keikosmile:20201206224734p:plain
できています!


それでは、二次元配列は、配列の中に要素として配列を持つのだから、こう書けばいいのかしら…
calendar = Array.new(3, Array.new(3, 0))
p calendar
calendar[0][1] = 2
puts calendar
f:id:keikosmile:20201206225139p:plain
…残念。初期化はうまくいっていますが、[0][1]要素に代入したことにより、[0][1]、[1][1]、[2][1]全ての要素が変化しています。
この書き方だと、[0]、[1]、[2]の要素が全て同じ配列オブジェクトを参照するようになっているようです。
(参照:Rubyで二次元配列の初期化


それでは、どう書けばいいかというと、結論は、
calendar = Array.new(3) { Array.new(3, 0) }
とし、Array.newにブロックを渡せば、0で初期化された3x3の二次元配列を作成することができるとわかりました。
p calendar
calendar[0][1] = 2
puts calendar
f:id:keikosmile:20201206230357p:plain
初期化がうまくいっていて、代入した後も、[0][1]要素しか変化していません!

 Rubyの標準ライブラリには多次元配列はなく、配列をネストすることで代用できます。特定の値で初期化するには、ブロック付きで「Array#new」を使用します。
 ただし、ネストした配列は代用品に過ぎず、範囲を超えたインデックスに代入したときに問題があります。本書では「擬似多次元配列」と呼ぶことにします。
 数値計算が目的ならばNArrayクラスを、行列計算が目的ならばMatrixクラスやVectorクラスを使用しましょう。
(参考:「改訂2版 Ruby逆引きハンドブック」)


ここまでたどりつくのが結構大変でしたので、ブログ記事に残すことができて良かったです!

Rubyのインストール

MacbookRubyをインストールしたので覚書です。

macにはrubyが既にインストールされている。
しかし、プロジェクト毎に使うRubyのバージョンは違うため、複数のRubyをインストールしておき、rbenvを使って切り替える必要がある。

使用環境 macOS catalina10.15.7

1. Command line tools

Homebrewを使うために必要。
XCodeiOS/MAC OS用アプリの統合開発環境 6GB程ある)をMac App Storeからインストールすると中に含まれているが、容量が大きいのでこちらの方法で行う

  1. Command line toolsをインストール
    xcode-select --install

参考資料
Rails Girls インストール・レシピ
MavericksでCommand Line Tools for Xcodeをインストールする - Qiita
Xcodeをインストールする方法【iOSアプリの統合開発環境】 | TechAcademyマガジン

2. Homebrew

MacOS用のパッケージ管理システム(Package Manager)
rbenvをインストールするために必要

  1. Homebrewをインストールする
    /user/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  2. brew doctor Homebrewに問題がないか確認
    Your system is ready to brew と表示されればOK
  3. brew update Homebrewをアップデートし最新パッケージリストを取得する
    Already up-to-date. と表示されればOK

    • brew search パッケージ名 パッケージを検索する
    • brew install パッケージ名 パッケージをインストールする
    • brew uninstall パッケージ名 パッケージをアンインストールする

    • brew list インストールされたパッケージのリストを表示する

    • brew upgrade Homebrewのアップデートに加えて、Homebrewでインストールしたパッケージのアップデートも行う
    • brew -v Homebrewのバージョンチェック
    • /user/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)" Homebrewとインストールしたパッケージのアンインストール

参考資料
MacにHomebrewを導入する方法 - Qiita https://qiita.com/3yatsu/items/47470091277d46f3fde2
Command Line Tools のインストール
brewのupdateとupgradeの違い - Qiita
【簡単】MacにHomebrewをインストールする方法と基本的な使い方|新卒エンジニアの開発日記

3. rbenv

異なったバージョンのRubyを切り替えるソフトウェア

  1. rvenvをインストール
    ruby-build(Rubyをインストールするrvenvのプラグイン)も同時にインストールされる
    brew install rbenv
  2. シェルにrbenvを設定する(rbenvを使い始める準備をするが 、ターミナルを開く毎に必ず実行する必要があるので、シェルの設定ファイルに追記する)。
    1. rbenv init
    2. ~/.zshrcにeval "$(rbenv init -)"を加える
  3. シェルを再起動する
  4. 適切にrbenvが設定されたか確認する curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash
  5. 公開されているRubyの安定版バージョンを表示する。
    rbenv install -l
  6. Ruby公式サイトでもRubyの安定版最新バージョンを確認する。
  7. Rubyの安定版最新バージョンをインストールする
    rbenv install 2.7.2
  8. Rubyの他の使いたい安定版バージョンをインストールする
    rbenv install 2.6.6
  9. インストールされrbenvが知ってい全Rubyバージョンを表示する
    現在アクティブなRubyバージョンには*が付いている
    rbenv versions
  10. 現在アクティブなRubyバージョンを表示する
    rbenv versionまたはruby -v
  11. 使用するRuyのバージョンを切り替える
    rbenv global 2.7.2

rbenv global と rbenv localの違い

fjordbootcampで質問し、回答いただき理解したことをまとめました。

rbenv global : 全体で有効になる

使用例
原則として安定版の最新バージョンのRubyを指定する

確認方法

  1. インストールされているRubyの各バージョンを確認 keikoimamura_—_-zsh_—_97×50.png
  2. 現在設定されているRubyの全体バージョンを確認する (「~/.rbenv/version」は全体バージョンの設定ファイル) keikoimamura_—_-zsh_—_97×50.png
  3. rbenv globalでRubyの全体バージョンを変更する keikoimamura_—_-zsh_—_97×50.png
  4. Rubyのバージョンが変わったことを確認する keikoimamura_—_-zsh_—_97×50.png

rbenv local : 今いるディレクトリだけで有効になる

使用例
プロジェクト毎に設定して、「このプロジェクトで使うRubyのバージョンはこれ」と固定する

確認方法

  1. 新しいディレクトリを作成し移動する new_dir_—_-zsh_—_97×50.png
  2. 現在のRubyのバージョンを確認する(まだ、globalで設定されたバージョンが有効になっている) new_dir_—_-zsh_—_97×50.png
  3. rbenv localでこのディレクトリでのRubyのバージョンを変更する 「.ruby-version」ファイル(このディレクトリだけで有効なバージョンが書き込まれている)が作成されている new_dir_—_-zsh_—_97×50.png
  4. このディレクトリのRubyのバージョンが変更されたことを確認する new_dir_—_-zsh_—_97×50.png
  5. homeディレクトリに戻り、Rubyの全体バージョンは変わっていないことを確認する keikoimamura_—_-zsh_—_97×50.png
  6. new_dirに戻り、「.ruby-version」ファイルを消すと、new_dirディレクトリも再びRubyの全体バージョンに依存するようになる new_dir_—_-zsh_—_97×50.pngnew_dir_—_-zsh_—_97×50.png

参考資料
rbenv/rbenv: Groom your app’s Ruby environment
パッケージ管理システム Homebrew
Mountain Lion に rbenv を導入 - hrysd の旧ブログ
RVMからrbenvに乗り換えてRuby2.0.0-p0を入れる - 納豆には卵を入れる派です。
【macOS Sierra】Mac OSX 10.12 macOS Sierra にRuby + Rails4 開発環境の構築 【初心者必見】 - Qiita
Homebrew + rbenv 環境の Ruby を 2.1.0 に変更する | deadwood
Ruby  バージョン変更に苦戦 | goemonhanaのブログ

標準入出力・リダイレクション・/dev/null・パイプ

ファイル(file)

コンピュータ上で記録・管理される情報の単位。UNIX/ Linux, Windows, Mac OS X等ほとんどのコンピュータシステムは、ファイルによるデータ管理を行っている。

標準入出力

コマンド(その実体であるプログラム)には、何らかの入力と出力がある。これを標準入力、標準出力と呼ぶ。

リダイレクション(re-direction)

通常、標準入出力はキーボードとディスプレイに結び付けられている。しかし、この結びつきを変更することができる。これをリダイレクションと呼ぶ。

標準入出力の数値

入出力チャンネル 数値
標準入力 0
標準出力 1
標準エラー出力 2
  • コマンド < ファイル名
    標準入力の入力元をキーボードではなくファイルに変更。
  • コマンド > ファイル名
    標準出力の出力先をディスプレイではなくファイルに変更。出力先のファイルが既存だった場合には、ファイルの先頭から結果を書き込む。
  • コマンド >> ファイル名
    標準出力の出力先をディスプレイではなくファイルに変更。出力先のファイルが既存だった場合には、ファイルの末尾に書き足す。
  • コマンド < 入力元ファイル名 > 出力先ファイル名 または
    コマンド > 出力先ファイル名 < 入力元ファイル名
    入出力の両方を変更する。
  • コマンド 2> ファイル名
    標準エラー出力の出力先をディスプレイではなくファイルに変更。出力先のファイルが既存だった場合には、ファイルの先頭から結果を書き込む。
  • コマンド > ファイル名 2> エラーファイル名
    標準出力と標準エラー 出力をそれぞれ別のファイルにリダイレクト。
  • コマンド > ファイル名 2>&1 または
    コマンド &> ファイル名
    標準出力と標準エラー出力を1つのファフィルにまとめてリダイレクト。

/dev/null

スペシャルファイル。入力先として指定しても何も内容を返さない。出力先として指定しても、書き込んだデータはどこにも保存されずに消えてなくなる。

コマンド < /dev/null
標準入力を空っぽにする(コマンドのテスト)
ls /xxxxx > /dev/null
標準出力を捨てる(コマンドの表示結果が大量にあり、標準エラー出力に表示されるエラーメッセージだけを読みたいとき)
ls /xxxx 2> /dev/null
エラーメッセージを非表示にしてコマンドの通常の出力結果だけを読み取る(エラーメッセージが大量に出るとき、あらかじめわかっているエラーメッセージが表示されるとき)
ls /xxxx > /dev/null 2>&1
標準出力と標準エラー出力を両方とも捨てる(あらかじめわかっている不要なメッセージを非表示にするとき、コマンドの実行時間を測る際メッセー出力を抑止したいとき)

パイプ

あるプログラムの標準出力を、他のプログラムの標準入力に接続すること。
コマンド | コマンド

参考資料
新しいLinuxの教科書(三宅秀明・大角祐介著) 標準入出力とパイプライン
stdio.pdf
Redirection( Shell ) 参考:Linuxでのパイプの活用方法

MacからDebian(さくらVPSサーバー)にssh接続する

ssh接続の設定が初心者には難しかったので備忘録を残します。
サーバー:Debian10.6
クライアント:macOS catalina10.15.7

1. (Macから)(Debianに)ssh接続をパスワード認証で行う

まずはいったんパスワード認証で接続する(後にパスワード認証は無効にする)。

  • ssh root@xxx.xxx.xx.xxx
    rootではデフォルトで拒否される(さくらVPSの場合)
  • ssh -l username xxx.xxx.xx.xxx
    一般ユーザーでは認証される

参考資料
ネコでもわかる!さくらのVPS講座 ~第二回「サーバーをさわってみよう!」 | さくらのナレッジ

2. (Debianで)sshサーバーの設定を変更して、rootで直接アクセスできないようにする

root権限で大切なファイルを消してしまうのを避けるため。

  1. cd /etc/ssh
  2. cp sshd_config sshd_config.old
  3. vim sshd_config
  4. #PermitRootLogin yesPermitRootLogin no
  5. sudo systemctl restart ssh
    sshdの再起動

3. (Debianで)sshサーバーのポート番号を変更する

セキュリティーホールを探す検索ロボットによる攻撃を避けるため。

  1. cd /etc/ssh
  2. cp sshd_config sshd_config.old
  3. `vim sshd_config
  4. #Port 22Port xxxxx
    xxxxxは新しいポート番号
    (ポート番号は0~65535番まであるが、0~1023のウェルノウンポートは避ける)(できるだけ大きい番号の方がいい)
  5. sudo systemctl restart ssh sshdの再起動

設定の確認
- ssh -p xxxxx -l username xxx.xxx.xx.xxx
- ssh -p 22 -l username xxx.xxx.xx.xxx 22番ポートではログインできない

参考資料
ウェルノウンポート(well-knownポート)とは - IT用語辞典 e-Words
SSHのポート番号を変更 - SSHサーバーの設定 - Linux入門 - Webkaru

4. (Macから)(Debianに)ssh接続を鍵認証で行う

セキュリティーホールを探す検索ロボットが適当なパスワードを入れて検索しているので、パスワード認証を無効にするため。

1) (Debianで).sshディレクトリを作成する

  1. mkdir ~/.ssh
  2. chmod 700 ~/.ssh

2) (Macで)RSA鍵を作成する

  1. ssh-keygen -t rsa パスワード不要ならEnter
  2. ls ~/.ssh 作成した鍵を確認する

3) (Macで)作成した公開鍵をDebianに送る

  1. scp -P xxxxx ~/.ssh/id_rsa.pub username@xxx.xxx.xx.xxx:~/.ssh/authorized_keys

4) (Debianで)受け取った公開鍵のパーミッションを変更する

  1. cd ~/.ssh
  2. chmod 600 authorized_keys
    所有者(自分のアカウント)だけが読み書きできる

5) (Macで)公開鍵でパスワードなしでssh接続できるか確認する

-ssh -p xxxxx username@xxx.xxx.xx.xxx

6) (Debianで)ssh接続を公開鍵認証のみにし、パスワード認証を不許可にする

-cd /etc/ssh
-cp sshd_config sshd_config.old
-vim sshd_config
-#PasswordAuthentication yesPasswordAuthentication no
-sudo systemctl restart ssh
sshdの再起動

参考資料
Mac OS X から Linuxサーバ へ、RSA 鍵を用いて SSH 接続する - joker8phoenix's diary
初期設定

Debianで使うaptコマンド(インストール)

apt(Advanced Packaging Tool)は、パッケージと呼ばれるコンパイル済みバイナリファイルのアーカイブを、パッケージ管理システムを利用してリポジトリからインストールするコマンドである。

  1. apt-cache search vim
    vimパッケージを検索する
  2. sudo apt-get install vim
    vimパッケージをインストールする
  3. sudo apt upgrade vim
    vimパッケージを更新する
  4. sudo apt-get remove vim
    vimパッケージを削除する。依存性のあるパッケージも自動的に削除される
  5. sudo apt edit-sources
    /etc/apt/sources.listにパッケージの入手先を追加する(直接編集するのではなく、apt edit-sourcesを使って編集すると書式を自動的にチェックできる)
  6. Devian 10/Busterのsources.listのデフォルト QEMU__ik1-449-56711_vs_sakura_ne_jp_.png

  7. deb http://ftp.jp.debian.org/debian buster main contrib non-free
    deb-src http://ftp.jp.debian.org/debian buster main contrib non-free
    deb http://security.debian.org/debian-security buster/udpdates main contrib non-free
    deb-src http://security.debian.org/debian-security buster/updates main contrib non-free

    • contribを追記…「ソフトウェア作成者によってフリーであるとされているが、他のフリーでないソフトウェアもインストールしないと使えないもの」もダウンロードできるようになる
    • non-freeを追記…「そのソフトウェアの利用や再配布に何らかの煩わしい制限があるもの」もダウンロードできるようになる。
    • 一般的なDebianユーザーはcontribとnon-freeを追記している場合が多いとのこと
  8. sudo apt update
    パッケージリストを再取得する

参考資料
【 apt 】コマンド(基礎編)――ソフトウェアをインストールする:Linux基本コマンドTips(139) - @IT
『新しいLinuxの教科書』(三宅秀明・大角祐介著)Chapter20 ソフトウェアパッケージ
Debianのsources.listの編集方法
apt-getの基本的なこと - 豆腐とコンソメ
SourcesList - Debian Wiki