ContentEditable を用いた Auto Expandable(?)なテキストエリアの実装

ContentEditableとは

HTML 要素を編集可能にする attribute *1*2HTML5 で実装された。
基本的な機能はほぼすべての主要なブラウザで実装されている。 *3

どんなときに使うか?

複数行の入力欄を実装するときにまず思いつくのは textarea *4 だと思う。
しかし標準の textarea では特定の文字の色を変えたり、WYSIWYG*5 エディタのようなリッチなテキストエリアを実装することができない。
ContentEditable を用いることによってリッチなテキストエリアを実現することができる。

Twitter のツイートの入力欄にも使われている。

twitter-draft-editor
Twitter のツイート欄

今回のTopic

一般的に textarea は縦方向に対して auto expandable(適当に名付けた。autoresize?)ではない。
表示される高さ(row count)が固定されており、行数が増えた場合は scrollable になる。
行数が変わったときに要素の高さも変えたい場合、不便である。

以下のような解決手法があるが、実装が面倒であったり自然な挙動にならない場合がある。 - JavaScript を用いて仮想的にコンテンツを描画して高さを取得し、動的に調整する - JavaScript を用いて 改行 を検知し、 row count を変更する そこで、適当な HTML element に対して contenteditable を付与することによって擬似的に auto expandable な textarea を実現できる。

実際に以下のコードで試してみる。

<p classname="Editor" role="textbox" contenteditable="true">
  Hello World
</p>

contenteditable-demo
contenteditable のデモ

React で使ってみる

普段 React を使って開発しているので React で使うときの注意点をいくつか書いておく。
contenteditable で変更を行った値は React で管理していないため、正しく store していないと "変更した結果が保存されないよ!" という旨の warning がでる。*6 suppressContentEditableWarning={true} を指定すると warning は消える。

contenteditable をつけたからと言って onChange が実装されているわけではないので、onChange は動かない。
そこで onBlur + ref などを用いてフォーカスが外れた際などに保存する必要がある。 onKeyDown は動くが、マウスを使って貼り付けを行った場合などは onKeyDown event は発行されないので注意する必要がある。

(追記 2021/05/25) input event が発行されるのでそちらを使ったほうが良さそう。*7

その他

  • フォーカスしたときに ブラウザが outline を勝手につけた場合は outline: 0px solid transparent;*8 を指定することによって outline を消せる
  • role="textbox" を指定することによってブラウザに入力可能要素であることを伝えられる*9

Example

サンプルコード

/* styles.css */
.App {
  font-family: sans-serif;
}

.Editor {
  padding: 16px;
  border-radius: 6px;
  border: solid 1px rgba(0, 0, 0, 0.12);
  background-color: rgba(0, 0, 0, 0.03);
  outline: 0px solid transparent;
}

.Editor:active,
.Editor:focus {
  background-color: rgba(0, 0, 0, 0.06);
  outline: 0px solid transparent;
}
/* App.jsx */
import { useState, useRef } from "react";
import "./styles.css";

export default function App() {
  const [value, setValue] = useState("Hello, World!");
  const ref = useRef(null);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
        <p
          className="Editor"
          ref={ref}
          role="textbox"
          contentEditable={true}
          suppressContentEditableWarning={true}
          onBlur={() => {
            setValue(ref.current.innerText);
          }}
        >
          {value}
        </p>
        <p>{value}</p>
    </div>
  );
}

最後に

ContentEditable を使って Auto Expandable なテキストエリアを実現する方法について書いてみたが、実際のプロダクトではメンテナンス性や安定性を考えると third-party のライブラリを使ったほうが良い。

2020年買ってよかったもの

こんにちは NotFounds です。 今年はアウトプットをしっかりしようと思っていたのですが気づいたら前回記事を書いてから一年経っていました。

年末定番ネタ(?)の「今年買ってよかったもの」を紹介したいと思います。

家電

テレビ 📺

今年買った一番大きい買い物*1です。
テレビ番組を見ることが目的ではなくリモートワークで使うために大きいディスプレイ*2が欲しいなぁと思って買ったのですが、遅延が気になったので YouTubeNetflix のための端末となってます。
有機 EL だけあってやはりがきれいです。

www.sony.jp

ウォータースタンド

購入というかサブスクなのですが、ウォータースタンドを導入しました。
水道直結型のウォーターサーバーで、本体のレンタル代と電気・水道代で利用することができます。
浄水されているとはいえ元は水道水なのでミネラルウォーターに味は劣りますが、一人暮らしで月に使う水の量が安定せず、またボトルの置き場所やゴミ出しを行う必要がないなど自分にはあってました。
今使っている機種はタンクがないためコンパクトなのですが、お湯を瞬間沸騰させるため微妙に煩わしいです。

waterstand.jp

空気清浄機

引っ越しして間もない花粉症の時期(2・3月頃)に購入しました。
加湿器や除湿機付きの機種も考えましたがメンテナンスが面倒そうなので空気清浄機機能のみの機種にしました。
効いているのか体感だとイマイチわかりませんが、半年のタイミングでフィルターを交換したところフィルターが悲惨なことになってたので無いよりはいいのかもしれません。

store.blueair.jp

電動歯ブラシ :toothbrush:

歯磨きが下手なので買いました。
スマホアプリで磨き残しがあったら分かるらしいですが、3日ほど使ったところ褒められてばかりで信用できなくなったのでアプリは使っていません。

分離キーボード ⌨️

今年買って一番良かった家電です。
以前から分離キーボードは持っており(BAROCCO MD650L | 株式会社アーキサイト)、今回はそれの後継っぽいものを買いました*3
静音赤軸本当に打ちやすいです。また、接続が USB Type-c になったのも地味に嬉しいです。
Bluetooth対応してほしいです。お願いします。

趣味

ダイビングライト 🤿🔦

御存知の通り、光は水中で吸収・散乱するため水深が深くなるにつれ波長の長い赤色は届かなくなります。
ダイビングでは10m~20mの水深にいることが多いですが、体感だと10m以深は灰っぽい色に見えます。
水中ライトを使って照らしてあげると、サンゴや魚の実際の色を見ることができます。
また、今回買ったライトはナイトダイブにも使える明るさで実際にナイトダイブで使いましが十分でした。

Tovatec Fusion 1500 - Top Rated Dive Lighttovatec.com

ライミングシューズ 🧗👟

今年に入ってからボルダリングをはじめました。
最近やっと中級レベルのグレードに手が届くようになってきたかなという感じで成長を実感しています。
EB の Electron というフラットタイプのシューズで ザ・入門 といった履きやすいシューズです。 そろそろ次のステップに向けてダウントゥのシューズが欲しくなってきました。

eb-climbing.com

その他

鉄フライパン 🍳

引っ越ししてコンロがガスになり、せっかくなので鉄フライパンを使ってみようということで買いました。
鉄フライパンについて調べると手入れが大変だと言う声が多いですが、温かいうちにたわしで洗うだけなのでそこまで苦ではないです。
肉がいい感じに焼ける気がします。気のせいかもしれません。

ディスプレイアーム

会社からリモートワークのための設備投資として補助金が出たので購入しました。
なおディスプレイが対応していなかったので2枚あるうちの1枚しかアームにつけていません。*4
ディスプレイの足を置く必要がないので、机が少し広くなった気がします。ちなみにディスプレイを動かしたことは半年間一度も無かったです。

Alfred

今年買ったものの中で最も生産性を上げてくれました。🎉
Mac を使っているなら絶対に使ったほうが良いと思います。
普段よく使う順に並べると以下のような感じです。

  • Web Search
  • GitHub 連携
  • Snippet 機能
  • Spotify 連携
  • Application 起動・切り替え
  • Clipboard 履歴

www.alfredapp.com

*1:物理的にも財布的にも

*2:65inchが欲しかったのですが部屋の入口が無くなりそうだったので諦めました

*3:正確には MD650L の方はロープロ仕様で Cherry ML 軸を使っていますが、MD770 は Cherry MX 軸を使っており シルバー・青・茶・赤・静音赤軸から選べます

*4:空いている方にはWebカメラを付けています。地味に便利です。

論文のバージョン管理とCI

皆さんこんにちは,ちゃんと論文書いていますか?もしかするとすでに書き終わっている方もいると思いますが,私は絶賛執筆中というか筆が全然進まなくて困っています. こんな記事を書いている場合ではない

「論文(だけじゃなくて形あるもの)はちゃんとバックアップをとっておけ!」と教員や先輩に口を酸っぱくして言われていると思います.実際バックアップを取っておいて損することはないですし絶対取っておいたほうが良いです(複数の環境にバックアップは起きましょう). いつ何時データが飛ぶかわかりません.私もつい先日,7年間ほどお世話になったPCの電源がつかなくなりました...

それはさておき複数の版を管理する場合,次のようにファイル名を変えて異なるバージョンを保存していく事があるかと思いますが,最終的にどれが"本当の"最終Verなのか分かりません.

卒論.tex
卒論_1.tex
卒論修正版.tex
卒論修正版(1).tex
卒論_先生コメント.tex
卒論最終.tex
卒論rev.tex
卒論_図rev.tex
sotsuron_final.tex
sotsuron.tex
thesis.tex

このような問題を解決する方法として,バージョン管理システムを使う方法があります.
また,最近はWordやGoogle document自体に版を管理する方法があるようですがTeXファイルなどのテキストファイルの版を管理するにはやはりバージョン管理システムを使うほかありません.
バージョン管理システムと検索すると大体SubversionかGitが出てくると思いますが,近年の流れとしてGitを使うのが主流です.正直個人で利用する分にはどちらでも問題ないです.

バージョン管理システムを導入することにより論文のバージョンをいい感じに管理することができましたが,まだバックアップは取れていません.
しかし,先に述べたバージョン管理システムGithubやBitbucketなどのソースコードホスティングサービスを使用することができ,そこにアップロード(Push)しておくことでバックアップを取る事ができます. ここで特に気をつけなければならないのは,GithubやBitbucketなどのリポジトリをPrivateにしておくことです.Publicにしてしまうと第三者が自由に見ることができてしまいます.

またGithubやBitbucketにはCI(Continuous Integration, 継続的インテグレーション)のための機能が含まれており,何らかのイベント(例えばコードの変更)のタイミングで指定したアクションを実行できます.
これを使うと新しく変更を加えPushしたタイミングでTeXファイルをコンパイルし,生成されたPDFをアップロードする事ができます.
メリットとしては, - ローカルにコンパイルする環境がなくても良い(環境に依存しない) - コンパイルに失敗する変更が特定できる - バージョンとそれに対応するPDFが保存される 等があると思います.

CIの設定

ここでは,GithubとBitbucketでの設定方法を述べます.
まず双方に共通するのがLaTeXコンパイル設定を記してある以下のファイルです.
ファイル名は.latexmkrcとしてリポジトリの直下に置いておきます.

#!/usr/bin/env perl
$pdf_mode         = 3;
$latex            = 'platex -halt-on-error';
$latex_silent     = 'platex -halt-on-error -interaction=batchmode';
$bibtex           = 'pbibtex';
$dvipdf           = 'dvipdfmx %O -o %D %S';
$makeindex        = 'mendex %O -o %D %S';

Github/Bitbucketともにpaperist/alpine-texlive-jaという公開されているDocker imageを使用させていただいています. それぞれの設定方法は以下に示します.

Github

Github用の設定です.
GithubではGithub Actionsという機能を使うのですが./github/workflow/というディレクトリに設定ファイルを置くと利用できます.
ここでは次にようにmain.ymlファイルを作成し,上記ディレクトリに配置します.

name: Build
on: [push]

jobs:
  build:
    runs-on: ubuntu-18.04
    steps:
    - uses: actions/checkout@v1
    - name: Build latex file
      uses: docker://paperist/alpine-texlive-ja
      with:
        args: latexmk index.tex

    - uses: actions/upload-artifact@v1
      with:
        name: index.pdf
        path: index.pdf

これをcommitしてGithubリポジトリにPushすると自動でコンパイルを行いPDFを生成します.
ここではTeXファイルの名前をindex.texとしていますが,異なるファイル名の場合適宜設定ファイルを変更してください.
結果はGithubのActionsというタブを開くと見ることができ,それぞれのBuildを開くとの右上にArtifactsというメニューが有りそこからPDFをダウンロードすることができます. Github Actionsの注意点としてはフリープランではPrivateリポジトリに対するGithub Actionsは2000分/月しか使うことができません.(一回のコンパイルは1~2分なのでそんなに影響ないですが...)複数のリポジトリを使っている場合は気をつけたほうが良いです.

Bitbucket

Bitbucket用の設定です.
BitbucketではPipelineという名前でGithubと同様の機能があります.これはbitbucket-pipelines.ymlという名前で設定ファイルを作成し,ディレクトリの直下に配置すると利用できます.

image: paperist/alpine-texlive-ja

pipelines:
  default:
    - step:
        script:
          - latexmk index.tex
        artifacts:
          - index.pdf

これをcommitしてButbucketのリポジトリにPushすると自動でコンパイルを行いPDFを生成します.
ここではTeXファイルの名前をindex.texとしていますが,異なるファイル名の場合適宜設定ファイルを変更してください.
結果はBitbucketのPipelinesというタブを開くと見ることができ,それぞれのBuildを開くとの右上に雲のマークのボタンが有りそこからPDFをダウンロードすることができます. Bitbucket pipelinesの注意点としてはフリープランでは50分/月しか使うことができません.Githubに比べて大分短いです.ちなみにStandard/Academicプランでは500分/月使うことができるのでこちらをおすすめします.

まとめ

論文はバージョン管理しましょう.
バージョン管理には適切なソフトを使用して決してファイル名で複数の版を管理するようなことをしてはいけません. リポジトリはPrivateに! GithubやBitbucket上でのCIの設定方法を示しました.

今後論文を書く方の参考になれば幸いです.

余談

弊研究室では行っていませんが,聞いた話によると論文のリポジトリに教授を招待し,IssueやPull Requestを通してレビューや修正を行っている研究室もあるようです.
レビューに関してはそれぞれやりやすい方法があると思うので一概には言えませんが,差分表示や行単位でのコメントに対応しているのでGithub等を用いてやり取りするのもいいですね.(作業量も可視化されてモチベーション上がるかもしれない)

また,ここでは紹介しませんでしたがtextlintと呼ばれる文書校正ツールが有りこれもCIに組み込むことができます.
ゼミ資料等を作成するときに使っていますが大変便利です.時間があればいつか書くかもしれません.

柿の種

注意:クソポエムです。 (この記事を書いたのは二年ほど前ですが、出すタイミングがなくて放置していました。そのため、時系列がおかしいことになっていますが大目に見てください)

今日は、何の日かご存知ですか?"目の愛護デー"世間ではそのように認識されていますが、実は「柿の種」の日でもあります。 柿の種おいしいですよね?きっとみんなも好きだと思います。
というわけで、柿の種について語りたいと思います。

本文

私は柿の種*1が好きです。 自宅と研究室には、柿ピー*2を常備しています。
また、私は柿ピー*3を食べる際、"ピーナッツを先に食し、後から柿の種のみを楽しむ"という変わった食べ方をします。

以前の私は、友人や家族に対しこのように言っていました。
柿ピーにピーナッツは必要無い!*4

ところで最近、少しづつお酒を飲むようになりました。
お酒のおツマミとして刺し身や焼鳥、揚げ物も良いですが、柿の種は任意のお酒のツマミになると考えています*5

先日、Amazon Surfing*6をしていたところ、このようなものを見つけました。

亀田製菓 亀田の柿の種100% 130g×12袋

亀田製菓 亀田の柿の種100% 130g×12袋

柿の種好きの私にとって買わない理由はありません。脊髄反射で1-click購入ボタンを押しました。

ピーナッツが入っておらず柿の種だけが入っているものはスーパやコンビニに売っているのですが、実はあるこだわりがあって「亀田製菓の柿の種」が大好きなのです。もちろん、他社の柿の種が嫌いなわけではありませんが私は亀田製菓の柿の種でなければ"満足"できないのです。

購入ボタンを押した次の日、箱いっぱいに詰め込まれた柿の種が届きました。普段は配達に2日ほどかかるのですが嬉しいことに今回は1日かかりませんでした。当然、柿の種が届くまで柿の種を食べながら待っていました(?)。

あぁこれだ。私が求めてたのはこれです。無我夢中で食べ続け、食後にも関わらずものの数分で一袋食べてしまいました。

ときには、お酒のツマミとして。
ときには、おやつや食後のデザートとして。
そしてときには、柿の種のお供として。

私は柿の種を食べ続けました。
箱いっぱいにあった柿の種はみるみるうちになくなり、ついに食べ終わりました。

「柿ピーにピーナッツは必要無い!」

以前、私はこのようなことを言っていましたが、柿の種のみを食べ続けていくうちにある重要なことに気付きました。 それは、
柿の種にはやはりピーナッツが合う!

私は柿ピーのことを何も理解していませんでした。
今までピーナッツなんてかさ増し程度の余分なものだと思っていたのですが、今回ピーナッツなし柿の種を食べ続けたことにより「ピーナッツがあるからこそ柿の種の美味しさが引き立つこと」という事に気付かされました。

結論

「柿ピーにピーナッツは必要無い!」なんて言ってすみませんでした。

これからは、ピーナッツが入っているこちらの商品を購入したいと思います。

亀田製菓 亀田の柿の種6袋詰 200g×6袋

亀田製菓 亀田の柿の種6袋詰 200g×6袋

まとめ

柿の種はいいぞ

*1:ここで言う柿の種とは、カキノキ科カキノキの果実の種のことではなく米菓のことを指します

*2:柿の種とピーナッツを混ぜ合わせたもの

*3:柿の種とピーナッツが一定の割合で混ぜ合わせてある菓子

*4:それは柿ピーではないのでは

*5:全てのお酒を飲んだことはないので想像ですが

*6:私が作った造語(既にあったらスミマセン)です。意味は、Amazonで適当に商品を眺めること。

CentOSで/homeを/にマージする

背景

現在,CentOSで構築しているサーバに外付けのSSDを接続し,そちらを/homeにマウントしている.
しかし,CentOSの初期設定の際に/homeには論理ボリュームcentos-homeが割り当てられていた.
centos-homeはどこにもマウントされていないためcentos-rootにマージしたい.

解決策

以下に示している解決法は「とりあえずやったらできた」程度のものです.
下記手順を実行したことによって生じた損害等の一切の責任を負いかねますのでご了承ください. (マサカリ🪓は歓迎します)

手順

流れとしては以下のようになります.
1. 論理ボリュームの確認
2. 現在/homeに存在するファイルの退避
3. 論理ボリュームcentos-homeの削除
4. 論理ボリュームが削除されたことの確認
5. 空いている容量を全てcentos-rootに割り当てる
6. 割り当てられたことの確認
7. OSが認識しているか確認
8. xfsファイルシステムを拡大
9. 正常にマウントされていることの確認

コマンド

(以下は全てrootで作業しています.)

1: 論理ボリュームの確認

まず,dfコマンドを用いてファイルシステムのディスク容量を確認します.以下の出力は/以外は省略してあります.現在,50GB中の約49GBを使用していることがわかります.

$ df -h
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root    50G   49G  1.6G   97% /

次にlvdisplayコマンドを用いて論理ボリュームの情報を表示します.ログを取るのを忘れており出力結果は表示していないのですが,rootとhomeの論理ボリュームが表示されてい(ました|る思います).

$ lvdisplay -C

2: 現在/homeに存在するファイルの退避

/homeに既にファイルがある場合は別の場所に退避させます.可能であれば他の物理ボリュームが良いと思います.*1 今回,/homeは空だったのでコマンドは省略しますが,圧縮して他の場所に置けば良いです.

3: 論理ボリュームcentos-homeの削除

ファイルを退避させたらlvremoveコマンドを用いて論理ボリュームを解放します.

$ lvremove /dev/mapper/centos-home

4: 論理ボリュームが削除されたことの確認

もう一度lvdisplayコマンドを用いて,削除されたことの確認を行います.

$ lvdisplay -C

5: 空いている容量を全てcentos-rootに割り当てる

lvextendコマンドを使い,空き容量を全て/に割り当てます.

$ lvextend -l +100%FREE /dev/mapper/centos-root

6: 割り当てられたことの確認

元々50GBでしたが,500GBになりました.(464.56GBとなっていますが,ファイルシステムが使用する容量があるためこのようになっていると推察されます)*2

$ lvdisplay -C
  LV   VG     Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root centos -wi-ao---- 464.56g

7: OSが認識しているか確認

ファイルシステムのディスク容量を確認します.

$ df -h 
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root    50G   49G  1.6G   97% /

🤔 🤔 🤔

サイズが増えていません.
これはこの時点ではまだファイルシステムのリサイズは行なっていないためです.

8: xfsファイルシステムの拡大

今回使用しているファイルシステムがxfsなので,xfs_growfsコマンドを用いて変更を反映します.

$ xfs_growfs -d / 
meta-data=/dev/mapper/centos-root isize=512    agcount=38, agsize=3276800 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=121782272, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=6400, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 13107200 to 121782272        

9: 正常にマウントされていることの確認

もう一度dfコマンドを用いてファイルシステムのディスク容量を確認します.

$ df -h 
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root  465G   49G  417G  11% /

正しく反映されました👍

参考

*1:最悪初期化することになるかもしれないので

*2:https://hesonogoma.com/linux/comparativetableoffilesystem.html

"ゼロからグレブナー基底入門"にいってきた

はじめに

突然ですがグレブナー基底をご存知ですか?
2017年冬,私は「妹がグレブナー基底に持ち始めたのだが。」*1というカクヨムの小説で出会いました.

"グレブナー基底"初めて聞いた(見た)その単語は刺激的で,ポン酢が似合いそうだなと思いました.嘘ですごめんなさい

ちなみに,上記小説は普段小説を避けている私が一気に最後まで読み進めてしまうくらい面白く,また高度な知識を必要としないため中高生でも読める内容になっています.

先日,上記小説の著者であるグレブナー基底大好きbot(@groebner_basis)さんが講師として務められるイベントが開催され,学生枠が空いていたので参加してきました. groebner-basis.peatix.com

勉強会

グレブナー基底の定義

 K: 体.多項式環 K[x_1, ..., x_n]のイデアル Iに対して,有限部分集合 G \subset Iの先頭項から生成されるイデアルが, Iの先頭項から生成されるイデアルに一致しているとき, G Iグレブナー基底と呼ぶ.すなわち,

一応独学で代数を勉強していますが,イデアルって何だっけ...? \mathrm{LT}ってなんだ??といったように自分で読み解くには時間がかかりそうでした.
一旦定義はおいておいて...

ここで,グレブナー基底の歴史やグレブナー基底の応用についてのお話がありました.
個人的には暗号理論への応用が気になりました.

次に, \mathrm{LT} (Leading Term, 先頭項)の説明,多変数多項式の割り算についての解説を受けました.

そして,もう一度定義に戻ってみると...?




_人人人人人人人人人人人人人_

> 読める!読めるぞ!!! <

 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄


最初に見たときに比べ,主張は理解できるようになってました.

講義の最後では,グレブナー基底を求めるブッフベルガーアルゴリズムの解説がありました.
計算量が多いとは聞いていましたが,  O(2^{2^{N}}) と聞いたときは笑ってしまいました. でも,実際に計算を行う分にはそこまでヤバくないらしい...?です.

演習

今回,2時間の講義と別に3時間の演習時間が設けられており,オンラインの計算ソフトWolfram|Alphaを使いながら演習問題を行いました.
演習問題では小説中に登場した嘘つきの問題を始め四色問題等が取り上げられ,それぞれ例題・基礎・発展があり十分なボリュームが有りました.
自分の手を動かして計算を行うのは久しぶりで,なんだかワクワクしました.

さいごに

勉強会では講義中に自由に質問できる機会を提供していただけたのは非常に良かったなと思います. 私もたくさん質問し,回答していただきました.
また,自分が気付かなかったことや認識が正確ではない部分に関して他の方が質問に対する回答を聞くことで理解することがありました.自分が疑問に思ったことは他の人も同様に悩んでいるかもしれないので,質問することは大事ですね.

正直私は数学科でもなければ特別数学が得意なわけでもないタダの数学が好きな人なので,数学の勉強会に参加するのは躊躇していました.
しかし,今回のイベントは"プログラマのための数学勉強会"さん主催で,前提知識が中高の数学だったので参加を決めました. 結果として,講義はめちゃくちゃ楽しくて学ぶことが多かったです.

これを期に,もう少し幅を広げて他分野の勉強会にも積極的に参加できたらなと思います.

紹介

今回の勉強会の講師を務められたグレブナー基底大好きbot(@groebner_basis)さんが執筆している書籍「妹がグレブナー基底に持ち始めたのだが。」の1巻と2巻は書泉さんで取り扱っています.*2 また,Amazon Kindle電子書籍が販売されています.(Kindle Unlimitedの方はなんと無料で読めます!)

togetter

今回,勉強会を主催されたさのたけと(@taketo1024)さんがまとめてくださいました. togetter.com

SSHでProxyCommandを使って多段ログインする

背景

次の図(?)ように,サーバA(踏み台サーバ)が外部ネットワークに公開されており,サーバB, C, ...(内部サーバ)には外部からアクセスできないようになっている環境はよくあります.

家 ----- インターネット ----- サーバA ----- サーバB
                                      +-- サーバC
                                      +-- etc...

このような環境で,外部から内部サーバにSSHでアクセスする方法として多段ログインがあります. 多段ログインとは,まず公開されている踏み台サーバにSSHで接続し,踏み台サーバから目的のサーバにSSHで接続することです.

しかし,毎回二度もSSHコマンドを叩くのは面倒なので一回コマンドを叩くだけで目的のサーバにアクセスできるようにします.

解決法

解決法には複数あり,ここではProxyCommandを使用した解決法を書きます.
ProxyCommandとはサーバへの接続に使用するコマンドを指定する機能です.(詳しくは$ man ssh_configに書いてあります)

とりあえず試す

まずはコマンドのみで試してます.
以下のように,SSHコマンドに-oオプションを付けてProxyCommandを指定します.

$ ssh -o ProxyCommand='ssh -p サーバーAのポート番号 -W %h:%p serverA' serverB

ここで,ProxyCommand内のSSHコマンドに渡している-Wというオプションはホスト名とポート番号を指定するオプションです.
また,ProxyCommandに指定した文字列の%h%pは接続先のホスト名に置換されます.
このコマンドを実行するとserverBに接続することができます.(鍵を指定していないためパスワードを聞かれると思います)

設定ファイルの編集

実際に接続できることを確認できました.
毎回長いコマンドを入力するのは面倒なので~/.ssh/configに設定を行います.

Host serverA
    HostName サーバAのIP(ホスト名)
    User サーバAのユーザー名
    Port サーバAのポート番号
    IdentityFile サーバAへの接続に使う鍵
Host serverB
    HostName サーバBのIP(ホスト名)
    User サーバBのユーザー名
    Port サーバBのポート番号
    IdentityFile サーバBへの接続に使う鍵
    ProxyCommand ssh -W %h:%p serverA

SSHコマンドを使ってアクセスしてみます.

$ ssh serverB

今度は鍵を指定しているためパスワードを入力することなくserverBに接続することができます.
これを応用すると,2段だけでなく3段階ログインといったことも可能です.