CINXE.COM
シグナルと kill コマンドについてちゃんと調べてみた | Basicinc Enjoy Hacking!
<!DOCTYPE html><html lang="ja" data-scope-path="layouts/application"><head prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article#"><link crossorigin="" href="https://www.google-analytics.com/analytics.js" rel="preconnect" /><link rel="preload" href="/fonts/noto-sans-jp-v24-japanese-regular.woff2" as="font" type="font/woff2" crossorigin="anonymous"><link rel="preload" href="/fonts/noto-sans-jp-v24-japanese-700.woff2" as="font" type="font/woff2" crossorigin="anonymous"><!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=UA-25666851-3"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-25666851-3'); </script> <link rel="stylesheet" media="all" href="/assets/ress-d1ba3a251927ab1f2bcc841c9a810109355bcb4260a522a0f76452fdc2fe6095.css" /><link rel="stylesheet" media="all" href="/assets/scopes/layouts/application-dda4ec688c139c8f29c39a2a795bcf4af04c4326643549a37f5d8843fffaebab.css" /><link rel="stylesheet" media="all" href="/assets/scopes/articles/show-37905516c06229c8fde10714e660fc48bc7b6ce7881755707db8b0327ceb5bf1.css" /><link rel="stylesheet" media="all" href="/assets/scopes/partials/_viewer-3a78a10250bb498047a06b71271b62ea949e304d25b9781c4450cf998aa2640c.css" /><link rel="stylesheet" media="all" href="/assets/scopes/layouts/_header-db87b54171cc020758ab7d1494677f8f6c2e9c93b453e896af82e4814eaacc7c.css" /><link rel="stylesheet" media="all" href="/assets/scopes/layouts/_breadcrumbs-744a099ab0b9eb5c4bd45215617e267c7d7c404ddddce8810eead5335512e637.css" /><link rel="stylesheet" media="all" href="/assets/scopes/layouts/_footer-a06961717440c6d0183c582c7f21768011f334d368f51b614eabc87bb17b3bbf.css" /><script src="/packs/application-02365dbc4dc28919eee1.js" defer="defer"></script><link href="/icon.png" rel="icon" type="image/png" /><link href="/apple-touch-icon.png" rel="apple-touch-icon" type="image/png" /><link href="/feed" rel="alternate" title="RSS2.0" type="application/rss+xml" /><title>シグナルと kill コマンドについてちゃんと調べてみた | Basicinc Enjoy Hacking!</title><meta name="csrf-param" content="authenticity_token" /> <meta name="csrf-token" content="zOh7sDMpvf+PhH25k0eTDBmizV6YaD289wq4fECi3R/MXJkc3cJ7qkyIeeZnCmBXsTgcxKwTGcYl/U1emLa3Jg==" /><meta content="width=device-width,initial-scale=1" name="viewport" /><meta content="シグナルと kill コマンドについてちゃんと調べてみた | Basicinc Enjoy Hacking!" property="og:title" /><meta content="article" property="og:type" /><meta content="2018-12-06T09:52:00+09:00" property="article:published_time" /><meta content="tkhr0" property="article:author" /><meta content="Technology" property="article:section" /><meta content="https://tech.basicinc.jp/articles/149" property="og:url" /><meta content="https://tech.basicinc.jp/uploads/24edf713de9af27d06ecc0045c1fd498.png" property="og:image" /><meta content="image/png" property="og:image:type" /><meta content="1200" property="og:image:width" /><meta content="630" property="og:image:height" /><meta content="開発中にプログラムが固まった時に kill プロセスID って打ったことがある方は多いかと思います 僕もそうで、 kill コマンドはプロセスを強制終了するためのコマンドだと思っていました ですが puma のログローテートを設定している時に kill -HUP って出てき..." property="og:description" /><meta content="ja_JP" property="og:locale" /><meta content="summary_large_image" name="twitter:card" /><meta content="@tkhr0" name="twitter:creator" /></head><body><header data-scope-path="layouts/_header"><div class="header-contents"><a class="root-link" href="/"><svg class="site-logo"><use xlink:href="/assets/icons-5bbe775037b55281ef0bc50d30a51f69c7c3914d399c7107e37f0702d98ae8a2.svg#logo"></use></svg><div class="site-title">Enjoy Hacking!</div></a><div class="site-desc">Basicinc エンジニアブログ</div></div></header><nav data-scope-path="layouts/_breadcrumbs"><ul class="breadcrumbs" itemscope="itemscope" itemtype="https://schema.org/BreadcrumbList"><span class="pretext">% cat </span> <li itemprop="itemListElement" itemscope="itemscope" itemtype="https://schema.org/ListItem"><a itemprop="item" href="/"><span itemprop="name">~</span></a><meta itemprop="position" content="1" /></li>/<li class="current" itemprop="itemListElement" itemscope="itemscope" itemtype="https://schema.org/ListItem"><span itemprop="name">シグナルとkillコマンドについてちゃんと調べてみた.md</span><meta itemprop="item" content="https://tech.basicinc.jp/articles/149" /><meta itemprop="position" content="2" /></li></ul></nav><div data-scope-path="articles/show"><article class="article"><h1 class="article-title">シグナルと kill コマンドについてちゃんと調べてみた</h1><div class="article-desc"><a class="article-author" href="/authors/5"><img class="article-author-avatar" src="https://tech.basicinc.jp/uploads/909284ed0c2d297ecacb5230440540ae.png" /><span class="article-author-name">tkhr0</span></a><div class="article-date-info"><time class="article-posted-date">Posted 2018-12-06</time></div></div><div class="article-body"><div data-scope-path="partials/_viewer"><p><img src="https://tech.basicinc.jp/uploads/e9a7d24cc60135311b72f0b9011db746.png" alt=""></p> <p>開発中にプログラムが固まった時に <code>kill プロセスID</code> って打ったことがある方は多いかと思います<br> 僕もそうで、 kill コマンドはプロセスを強制終了するためのコマンドだと思っていました</p> <p>ですが puma のログローテートを設定している時に <code>kill -HUP</code> って出てきてなんだこれ?ってなりました<br> あれ?ログファイルを握り直すのに <code>kill</code> 使うの??プロセスを止めたいなんて思ってないよ???みたいな</p> <p>なのでちゃんと調べてみました</p> <h1>TL;DR</h1> <ul> <li>kill コマンドはプロセスに対して「シグナル」を送信するためのコマンド</li> <li>シグナルはプロセスがプロセス外でのイベントに対して対応するための機構 <ul> <li>シグナルには定義があってそれごとにデフォルト動作がある</li> <li>シグナルの動作は上書きすることも可能</li> </ul> </li> </ul> <h2>今回のシチュエーション</h2> <p>logrotate で <a href="https://github.com/puma/puma">puma</a> のログファイルをローテーションしたい、という状況でした<br> なので、いろいろとググって下記の設定をしました</p> <pre lang="bash" class="highlight-bash">lastaction <span class="nv">puma_pid</span><span class="o">=</span>/tmp/pids/puma.pid <span class="nb">test</span> <span class="nt">-s</span> <span class="nv">$puma_pid</span> <span class="o">&&</span> /usr/bin/kill <span class="nt">-HUP</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">cat</span> <span class="nv">$puma_pid</span><span class="si">)</span><span class="s2">"</span> endscript </pre> <p>これは logrotate がログファイルを切り替えた後に行う処理です<br> これをやらないと puma がログを吐き出すことができなくなってしまいます</p> <p>今回のキモは <code>kill -HUP</code> ですね<br> puma を止めたいわけじゃない(ログを切り替えたい)のに <code>kill</code> してます<br> しかも謎の <code>-HUP</code> 指定もしてます</p> <p>どういうことよ <img draggable="false" title=":thinking_face:" alt="🤔" src="https://twemoji.maxcdn.com/2/svg/1f914.svg" class="emoji" loading="lazy"></p> <h2>kill コマンドの機能について</h2> <p>kill コマンドはプロセスを強制終了するためのコマンドだと思っていましたが、違う雰囲気を感じます<br> なのでちゃんと kill コマンドの man を見ました</p> <blockquote> <p>kill コマンドは、指定したシグナルを指定したプロセスまたはプロセスグループへ送る。シグナルが指定されない場合、TERMシグナルを送る。</p> </blockquote> <p><a href="https://linuxjm.osdn.jp/html/util-linux/man1/kill.1.html">https://linuxjm.osdn.jp/html/util-linux/man1/kill.1.html</a></p> <p>プロセスの強制終了なんて一言も書いてません<br> ~~ なんて紛らわしいコマンド名でしょうか ~~<br> kill コマンドはシグナルをプロセスに送るコマンドです</p> <p>「シグナル」と「プロセス」というキーワードが2つ出てきていますが<br> プロセスはあるプログラムを指すと理解しておきます<br> シグナルってなんぞや <img draggable="false" title=":thinking_face:" alt="🤔" src="https://twemoji.maxcdn.com/2/svg/1f914.svg" class="emoji" loading="lazy"></p> <h2>シグナルとは</h2> <p>なんらかのイベントが起こったことをプロセスに通知するための機構です<br> イベントを受け取ったプロセスは、イベントの種類によってなんらかの処理をします<br> 受け取る側のプロセスは自身の実行とは別で受け取ることができます</p> <p>イメージは Javascript の <code>addEventListener</code> が近いと思います<br> なんらかのイベントが発生したらそれに対応する関数が実行されます<br> 例えば下の場合です</p> <pre lang="javascript" class="highlight-javascript"><span class="kd">var</span> <span class="nx">select</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">select</span><span class="dl">'</span><span class="p">)</span> <span class="c1">// L1</span> <span class="nx">select</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="c1">// L2</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">clicked!</span><span class="dl">'</span><span class="p">)</span> <span class="c1">// L3</span> <span class="p">})</span> <span class="nx">select</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">change</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="c1">// L5</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">changed!</span><span class="dl">'</span><span class="p">)</span> <span class="c1">// L6</span> <span class="p">})</span> </pre> <p>なんらかのイベントが起こったこと (L2) をプロセス (L1) に通知するための機構です<br> イベントを受け取ったプロセスは、イベントの種類 (L2, L5) によってなんらかの処理 ( L3, L6 ) をします</p> <h2>シグナルが登場する場面</h2> <p>普段の開発でシグナルの送信を意識していない方も多いかと思います<br> ですが、以外とシグナルを送信している機会は意外とあります</p> <p>例にあげた <code>kill</code> もその1つです<br> オプションに <code>-KILL</code> や <code>-9</code> をつけて実行すると対象のプロセスに対して <code>SIGKILL</code> というシグナルを送信しています<br> <code>kill</code> (オプションなし) の場合は <code>SIGTERM</code> というシグナルを送信しています</p> <p>また terminal でよく使う <code>Ctrl-c</code> もプロセスに対してシグナルを送信しています<br> <code>Ctrl-c</code> を入力するとプロセスに対して <code>SIGINT</code> というシグナルが送信されます<br> 同じく <code>Ctrl-z</code> は <code>SIGTSTP</code> を送信しています</p> <p>これは javascript だとブラウザ上で何かのアクションが起きた時(クリックとかスクロールとか)をイメージしてもらうと近いかと思います<br> その場合イベントハンドラ <code>console.log('clicked!')</code> とかするところはどうなるのでしょうか <img draggable="false" title=":thinking_face:" alt="🤔" src="https://twemoji.maxcdn.com/2/svg/1f914.svg" class="emoji" loading="lazy"></p> <h2>シグナル送信後の挙動</h2> <h3>デフォルトの挙動</h3> <p>シグナルを受け取ったプロセスは、そのシグナルの種類によってなにかしらの処理をします<br> 基本的にはシグナルごとに定義されているデフォルトの処理が行われます<br> 一部を紹介するとこうなっています</p> <table> <thead> <tr> <th align="left">シグナルの種類</th> <th align="center">デフォルトの動作</th> <th align="left">備考</th> </tr> </thead> <tbody> <tr> <td align="left">SIGINT</td> <td align="center">終了</td> <td align="left">キーボードからの割り込み (Interrupt)</td> </tr> <tr> <td align="left">SIGTSTP</td> <td align="center">停止</td> <td align="left">terminal から入力される時停止</td> </tr> <tr> <td align="left">SIGKILL</td> <td align="center">終了</td> <td align="left">kill シグナル</td> </tr> <tr> <td align="left">SIGTERM</td> <td align="center">終了</td> <td align="left">termination 終了シグナル</td> </tr> <tr> <td align="left">SIGHUP</td> <td align="center">終了</td> <td align="left">terminal のハングアップや制御しているプロセスの死</td> </tr> </tbody> </table> <p><a href="http://linuxjm.osdn.jp/html/LDP_man-pages/man7/signal.7.html">http://linuxjm.osdn.jp/html/LDP_man-pages/man7/signal.7.html</a></p> <p>プログラムを停止したい時に <code>Ctrl-c</code> を押せばいい、というのはこういうことですね<br> つまり <code>Ctrl-c</code> を押すと <code>SIGINT</code> シグナルがプロセスに送信され、デフォルトの挙動である「終了」処理を行うからです</p> <h3>デフォルト挙動の上書き</h3> <p><code>SIGINT</code> を受け取ったプロセスは終了処理を行いますが、これはあくまでもデフォルトで定義された挙動でしかなく別の処理をさせる(キャッチ)こともできます</p> <p>例えば <code>less</code> コマンドのの場合、 <code>less</code> を起動してから <code>Ctrl-c</code> を押下してもプロセスは終了しません<br> これはデフォルトの終了という挙動を上書きしているからです<br> つまり、あるシグナルに対してなにをするのかはそのプログラムの実装による、ということです<br> 逆に、プログラムはシグナルを受け取ることで外部の任意のタイミングで規定の動作を受け付けることができる、とも言えます</p> <p>javascript でいえば、 form の submit をフックして submit 前にバリデーションを挟む、的な挙動をさせるのに似てますね</p> <pre lang="javascript" class="highlight-javascript"><span class="kd">var</span> <span class="nx">form</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">form</span><span class="dl">'</span><span class="p">)</span> <span class="nx">form</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">submit</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">evt</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="nx">do_validations</span><span class="p">()</span> <span class="o">==</span> <span class="kc">false</span><span class="p">)</span> <span class="p">{</span> <span class="nx">evt</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span> <span class="p">}</span> <span class="p">})</span> </pre> <p>補足ですが、シグナルはキャッチする以外にブロックしたり無視することができます<br> ただし <code>SIGKILL</code> と <code>SIGSTOP</code> はキャッチ、ブロック、無視することはできません</p> <h2> <code>kill -HUP</code> の解読</h2> <p>さて、話を戻して今回のシチュエーション <code>kill -HUP</code> がなんなのかという件です<br> 具体的には puma のログファイルに対する logrotate の中で、 puma にログファイルを握り直してもらうために <code>kill -HUP {puma のプロセス}</code> をします</p> <p>まず <code>kill -HUP</code> です<br> <code>kill</code> コマンドを使って puma に対して <code>SIGHUP</code> のシグナルを送信しています<br> <code>SIGHUP</code> は前述の通り terminal のハングアップや制御しているプロセスの死を表し、デフォルトではプロセスは終了します</p> <p>ですが実際には puma のプロセスは終了しないので意味不明です <img draggable="false" title=":thinking_face:" alt="🤔" src="https://twemoji.maxcdn.com/2/svg/1f914.svg" class="emoji" loading="lazy"><br> なので落ち着いて <a href="https://github.com/puma/puma/blob/master/docs/signals.md#puma-signals">puma の wiki</a> を参照しましょう</p> <blockquote> <p>Puma cluster responds to these signals:<br> <code>HUP</code> reopen log files defined in stdout_redirect configuration parameter.</p> </blockquote> <p>puma は <code>HUP</code> を受け取るとログファイルをリオープンします<br> とあります</p> <p>つまり puma は <code>SIGHUP</code> をキャッチして、プロセスの終了をする代わりにログファイルを握り直してくれます</p> <p>ということで、これで理解できましたね<br> 「logrotate の中で puma に対して <code>SIGHUP</code> シグナルを送信することで、<br> puma が <code>SIGHUP</code> シグナルに対して独自に定義した『ログファイルをリオープンする』という動作をさせる」<br> という設定でした</p> <h2>補足</h2> <h3>シグナルの値について</h3> <p>シグナルには名前とともに値が割り振られています</p> <table> <thead> <tr> <th align="left">シグナルの種類</th> <th align="center">値</th> <th align="center">デフォルトの動作</th> <th align="left">備考</th> </tr> </thead> <tbody> <tr> <td align="left">SIGHUP</td> <td align="center">1</td> <td align="center">終了</td> <td align="left">terminal のハングアップや制御しているプロセスの死</td> </tr> <tr> <td align="left">SIGINT</td> <td align="center">2</td> <td align="center">終了</td> <td align="left">キーボードからの割り込み (Interrupt)</td> </tr> <tr> <td align="left">SIGKILL</td> <td align="center">9</td> <td align="center">終了</td> <td align="left">kill シグナル</td> </tr> <tr> <td align="left">SIGTERM</td> <td align="center">15</td> <td align="center">終了</td> <td align="left">termination 終了シグナル</td> </tr> </tbody> </table> <p><code>kill</code> コマンドを使ってプロセスを停止させるときに <code>kill -KILL</code> としたり <code>kill -9</code> としたりすると思います<br> <code>kill</code> コマンドはオプションでシグナル名かシグナル値を受け取ります<br> なので <code>-KILL</code> と <code>-9</code> はどちらも <code>SIGKILL</code> を送信するので同じ挙動になります</p> <h3>シグナルをキャッチする</h3> <p>C 言語でシグナルをキャッチするためには <code>sigaction</code> 関数を使います<br> <a href="https://linuxjm.osdn.jp/html/LDP_man-pages/man2/sigaction.2.html">https://linuxjm.osdn.jp/html/LDP_man-pages/man2/sigaction.2.html</a><br> <code>signal</code> 関数もあるんですが、歴史的背景から非推奨なようです</p> <p>ruby の場合は <code>Signal.#trap</code> でキャッチできます<br> <a href="https://docs.ruby-lang.org/ja/latest/method/Signal/m/trap.html">https://docs.ruby-lang.org/ja/latest/method/Signal/m/trap.html</a><br> puma だとこんな感じ<br> <a href="https://github.com/puma/puma/search?q=signal+trap&unscoped_q=signal+trap">https://github.com/puma/puma/search?q=signal+trap&unscoped_q=signal+trap</a></p> <h3>nginx の logrotate の場合</h3> <p>puma で logrotate をするように nginx でも logrotate していたのでついでに調べてみました<br> ec2 で nginx をインストールすると logrotate が自動で設定されていました</p> <pre lang="nginx" class="highlight-nginx"><span class="k">postrotate</span> <span class="n">/etc/init.d/nginx</span> <span class="s">reopen_logs</span> <span class="s">endscript</span> </pre> <p>これだとわかりにくいので公式サイトを参照すると</p> <blockquote> <p>NGINX will re-open its logs in response to the USR1 signal.<br> <code>$ kill -USR1 `cat master.nginx.pid` </code></p> </blockquote> <p><a href="https://www.nginx.com/resources/wiki/start/topics/examples/logrotation/">https://www.nginx.com/resources/wiki/start/topics/examples/logrotation/</a></p> <p>もうわかりますね<br> <code>SIGUSR1</code> シグナルを送信しています</p> <p><code>SIGUSR1</code> は初出ですが、デフォルトの動作は「終了」でこれは「ユーザー定義シグナル1」というシグナルです<br> 好きに使っていいよ、って感じですかね<br> nginx でログローテートする場合は puma より素直でに好きに使っていいよシグナルを介してログファイルを握り直してくれるみたいです</p> <h3>unicorn の logrotate の場合</h3> <p>puma と nginx を見てきたのでついでに unicorn も見てみます</p> <p>公式サイトのシグナルハンドリングの項に書いてありました</p> <blockquote> <p>USR1 - reopen all logs owned by the master and all workers See Unicorn::Util.reopen_logs for what is considered a log.</p> </blockquote> <p><a href="https://bogomips.org/unicorn/SIGNALS.html">https://bogomips.org/unicorn/SIGNALS.html</a></p> <p>ということで nginx と同じく <code>USR1</code> シグナルを送信すれば良さそうですね</p> <h2>まとめ</h2> <p>シグナルと <code>kill</code> コマンドについて調べてみました<br> 出会う機会は少なかったりなんか難しそうだったのでなんとなくで流してしまっていましたが、ちゃんと調べてみればなんてことはなかったです</p> <h2>参考</h2> <ul> <li><a href="https://linuxjm.osdn.jp/html/util-linux/man1/kill.1.html">https://linuxjm.osdn.jp/html/util-linux/man1/kill.1.html</a></li> <li><a href="https://linuxjm.osdn.jp/html/LDP_man-pages/man2/sigaction.2.html">https://linuxjm.osdn.jp/html/LDP_man-pages/man2/sigaction.2.html</a></li> <li><a href="http://archive.linux.or.jp/JF/JFdocs/The-Linux-Kernel-6.html">http://archive.linux.or.jp/JF/JFdocs/The-Linux-Kernel-6.html</a></li> <li><a href="https://www.ohmsha.co.jp/book/9784274079726/">Linuxシステムプログラミング</a></li> </ul></div></div><div class="article-sns-share-buttons"><a rel="nofollow" target="_blank" class="pocket-share sns-share-button" href="http://getpocket.com/edit?title=%E3%82%B7%E3%82%B0%E3%83%8A%E3%83%AB%E3%81%A8+kill+%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%81%A1%E3%82%83%E3%82%93%E3%81%A8%E8%AA%BF%E3%81%B9%E3%81%A6%E3%81%BF%E3%81%9F+by+tkhr0+%7C+Basicinc+Enjoy+Hacking%21&url=https%3A%2F%2Ftech.basicinc.jp%2Farticles%2F149"><svg class="sns-icon pocket-icon"><use xlink:href="/assets/icons-5bbe775037b55281ef0bc50d30a51f69c7c3914d399c7107e37f0702d98ae8a2.svg#pocket"></use></svg></a><a rel="nofollow" target="_blank" class="hatena-share sns-share-button" href="http://b.hatena.ne.jp/add?mode=confirm&title=%E3%82%B7%E3%82%B0%E3%83%8A%E3%83%AB%E3%81%A8+kill+%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%81%A1%E3%82%83%E3%82%93%E3%81%A8%E8%AA%BF%E3%81%B9%E3%81%A6%E3%81%BF%E3%81%9F+by+tkhr0+%7C+Basicinc+Enjoy+Hacking%21&url=https%3A%2F%2Ftech.basicinc.jp%2Farticles%2F149"><svg class="sns-icon hatena-icon"><use xlink:href="/assets/icons-5bbe775037b55281ef0bc50d30a51f69c7c3914d399c7107e37f0702d98ae8a2.svg#hatena"></use></svg></a><a rel="nofollow" target="_blank" class="twitter-share sns-share-button" href="https://twitter.com/share?text=%E3%82%B7%E3%82%B0%E3%83%8A%E3%83%AB%E3%81%A8+kill+%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%81%A1%E3%82%83%E3%82%93%E3%81%A8%E8%AA%BF%E3%81%B9%E3%81%A6%E3%81%BF%E3%81%9F+by+tkhr0+%7C+Basicinc+Enjoy+Hacking%21&url=https%3A%2F%2Ftech.basicinc.jp%2Farticles%2F149"><svg class="sns-icon twitter-icon"><use xlink:href="/assets/icons-5bbe775037b55281ef0bc50d30a51f69c7c3914d399c7107e37f0702d98ae8a2.svg#twitter"></use></svg></a><a rel="nofollow" target="_blank" class="facebook-share sns-share-button" href="http://www.facebook.com/share.php?u=https%3A%2F%2Ftech.basicinc.jp%2Farticles%2F149"><svg class="sns-icon facebook-icon"><use xlink:href="/assets/icons-5bbe775037b55281ef0bc50d30a51f69c7c3914d399c7107e37f0702d98ae8a2.svg#facebook"></use></svg></a></div></article></div><footer data-scope-path="layouts/_footer"><div class="footer-contents"><a class="root-link" href="/"><svg class="site-logo"><use xlink:href="/assets/icons-5bbe775037b55281ef0bc50d30a51f69c7c3914d399c7107e37f0702d98ae8a2.svg#logo"></use></svg><div class="site-title">Enjoy Hacking!</div></a><ul class="link-list"><li class="link-list-item"><a class="link" href="https://basicinc.jp/" rel="noopener" target="_blank">株式会社ベーシック</a></li><li class="link-list-item"><a class="link" href="https://basicinc.jp/enjoy-hacking" rel="noopener" target="_blank">エンジニア募集</a></li><li class="link-list-item"><a class="link" href="https://qiita.com/organizations/basicinc" rel="noopener" target="_blank">Qiita</a></li><li class="link-list-item"><a class="link" href="https://www.wantedly.com/companies/basicinc/projects" rel="noopener" target="_blank">Wantedly</a></li></ul></div></footer></body></html>