memo-pad’s blog

自分のためのメモをまとめています。ここに書いてある内容については責任は負いません。全て自己責任でお願いします。

Visual Studio Codeでリモートサーバのファイルを編集する

今回使ったのはこちらのRemote VSCode marketplace.visualstudio.com

今回の環境

  • ローカル
linux mint 18.1
Visual Studio Code 1.16.1
Remote VSCode 1.1.0
  • リモート
ubuntu 16.04
rmate 1.0.0 (shell script版)

ローカルの設定

Remote VSCodeのインストール

  1. Visual Studio CodeでCtrl-pを押し、ext install remote-vscodeと入力後、Enter f:id:memo-pad:20171008210225p:plain

  2. 拡張機能の検索結果が表示されるので、Remote VSCodeをインストール f:id:memo-pad:20171008210229p:plain

  3. 拡張機能を再読み込みさせRemote VSCodeを有効化 f:id:memo-pad:20171008210232p:plain

Remote VSCodeの設定変更

  1. 「ファイル」-「基本設定」-「設定」からユーザ設定を開く f:id:memo-pad:20171008210235p:plain

  2. ユーザ設定のRemote VSCode Configurationが下記のような値になっているので、remote.onstartuptrueに変更する f:id:memo-pad:20171008210238p:plain f:id:memo-pad:20171008210240p:plain

Remote VSCode用のsshトンネルを作成

  1. 端末でリモートサーバとのssh tunnelを作成する
ssh -R 52698:127.0.0.1:52698 [リモートサーバのユーザ名]@[リモートサーバのホスト]

リモートの設定

今回はruby版ではなく、shell script版を利用する github.com

rmateのインストール

  1. rmateをダウンロードし、実行権限を付与
sudo wget -O /usr/local/bin/rmate https://raw.github.com/aurora/rmate/v1.0.0/rmate
sudo chmod a+x /usr/local/bin/rmate
  • 補足:最新版を入れるなら下記コマンド
sudo wget -O /usr/local/bin/rmate https://raw.github.com/aurora/rmate/master/rmate

rmateの実行

  1. リモートサーバで下記コマンドを実行すると、ローカルのVisual Studio Codeで指定したファイルが表示される
rmate -p 52698 [編集したいファイル名]
  • 注意
    • リモートサーバとのsshトンネルが切れていると失敗します
    • ローカル側でVisual Studio Codeを事前に立ち上げておかないと失敗します

更新の同期方法

ローカルでの更新内容をリモートに同期

  1. Visual Studio Codeで更新したファイルを保存するだけ

リモートでの更新内容をローカルに同期

  1. リモートのファイルを編集するときと同じ
rmate -p 52698 [更新したファイル名]

slackcatでconfigが読み込めない時

いつも通り~/.config/slackcat/configにconfigファイルを配置しても下記エラーが出て読み込めない。

slackcat missing config file at <configのパス名>
use --configure to create

コードを読んでみる

xdgの有無でconfig読む先が変わるようだ

参考:https://github.com/vektorlab/slackcat/blob/v1.3/config.go#L97-L105

configのパスの挙動

具体的にはこんな感じになる(xdgの有無は環境変数にXDG_で始まるものがあるかで判別してるっぽい)

  • xdgがない:$HOME/.slackcatに配置
  • xdgがある:
    • 環境変数にXDG_CONFIG_HOMEがある:$XDG_CONFIG_HOME/slackcat/config
    • 環境変数にXDG_CONFIG_HOMEがない:$HOME/.config/slackcat/config

オチ

そして、ここまで調べてManualにちゃんと書いてあることに気づく

参考:https://github.com/vektorlab/slackcat/blob/v1.3/docs/configuration-guide.md#default-path

If your environment specifies an XDG Base Directory, slackcat will use the configuration file at ~/.config/slackcat/config; otherwise, will fallback to ~/.slackcat

しかも、最初のエラーメッセージで<configのパス名>を表示してくれているので、そこに配置すれば良いだけだったりする

Docker内のNode.jsで作成したhttpサーバにアクセスできない

最近Docker上でNode.jsを動かして遊んでます。

遊んでる際に、Docker内のnodeで作ったhttpサーバにアクセスできないという問題があったのでメモ。

今回利用したファイル

  • test.js(ただ単にHelloWorldを返すだけのもの)
var http = require('http');
var server = http.createServer();

server.on('request', function(req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.write('Hello World!!');
  res.end();
})

server.listen(1234, '127.0.0.1');
  • Dockerfile.node(nodeの実行環境作って、test.jsを動かしているだけ)
FROM centos:centos7
MAINTAINER memo

# package install
RUN yum update -y && \
 yum install -y vim && \
 yum clean all

# node install
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash && \
 export NVM_DIR="$HOME/.nvm" && \
 [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" && \
 nvm install v8.0.0


ENV PATH=/root/.nvm/versions/node/v8.0.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ADD test.js /root/test.js
EXPOSE 1234
CMD ["node", "/root/test.js"]

実際に行った手順

  • docker buildでDocker Imageを作成
$ sudo docker build --tag="centos7/node:v1.0" --file="/home/dockerroot/Dockerfile.node" .
  • 作成したImageからコンテナ起動
$ sudo docker run -d centos7/node:v1.1
  • 作成したアプリにアクセス
$ curl localhost:1234
curl: (7) Failed to connect to localhost port 1234: Connection refused

……つながらない

ここから試行錯誤

  • 試しにコンテナ内でcurlしてみる
$ sudo docker run -it centos7/node:v1.1 bash
# cd
# node test.js &
# curl localhost:1234
Hello World!!

いけた!!

  • ポートが設定されてないのかなとdocker ps をみてもportsに1234は設定されている……
$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
d38253600f9b        centos7/node:v1.1   "node /root/test.js"   2 minutes ago       Up 2 minutes        1234/tcp            happy_khorana

もしかしたら、DockerfileのEXPOSE 1234の設定だけではポートマッピングが不十分なのか??

  • ポートマッピングをちゃんと指定してコンテナを走らせてみる
$ sudo docker run -p 1234:1234 -d centos7/node:v1.1
  • 作成したアプリにアクセス
$ curl localhost:1234
curl: (52) Empty reply from server

今度はポート自体はちゃんと設定されているっぽい。

ただ、ちゃんとhttpサーバからのresponseが返ってきてない??

  • よくわからないけど、試しにtest.jsのserver.listenのIPを0.0.0.0に変更してみる
server.listen(1234, '127.0.0.1');
↓

server.listen(1234, '0.0.0.0');
  • 再度アプリにアクセス
$ curl localhost:1234
Hello World!!

お!いけた!

やったことまとめ

  • server.listenのIPアドレスを0.0.0.0にした
  • docker runでコンテナ作成するときに-pオプションでポートを指定した

ただ、やり方的にこれが正しいかどうか、Node.jsもDockerも勉強中なのでわからない……

今後、触っていってわかったことがあったら追記していきます。

phpのcodegolf Tips

先日、身内でCodegolfをやったので、その時に学んだショートコーディングの知識をメモ

Codegolfというのは如何に文字数を少なくコードを記述するかを競う競技です。
コードゴルフ - Wikipedia

それではTipsのメモを書いていきます。

出力に改行を出したいときには\nは使わない

例えばこんなコード

echo "test\n";

こう書けば1文字少なくできます(改行分は1文字扱いのため2文字削減にはならない)

echo "test
";

関数にエイリアスがないかを確認する

例えば配列を結合して文字列にしたいときに下記のようにimplodeを使いますよね?

implode($array);

実はimplodeにはjoinというエイリアスが設定されているので、下記のように変更可能です。

join($array);

これだけで3文字分削減です。

ちなみにphpエイリアスhttp://php.net/manual/ja/aliases.phpに載っています。

foreachのas前後のスペースを削る

例えば通常だと下記のようにforeachを記述すると思います。

foreach($a as $b){}

しかし、実は下記のようにasと$bがくっついていても問題ありません。

foreach($a as$b){}

また、先頭が配列形式だったり、カッコがある場合はこんな風にくっつけても問題ないです。

foreach($a[0]as$b){}
foreach(explode(',',$a)as$b){}

要するにちゃんとパースしてくれそうな形式ならas前後にスペースはいらないということですね。

可変変数を使う

可変変数の詳しい説明はこちらPHP: 可変変数 - Manual

例えばa,b,cという文字が出現する回数を数える場合、普通ならこんな感じにかけます。

for(;$i=fgetc(STDIN);){++$a[$i];}
foreach(str_split("abc")as$v){echo $a[$v];}

ここで可変変数を使うとこうかけたりします。

for(;$i=fgetc(STDIN);){++$$i;}
foreach(str_split("abc")as$v){echo $$v;}

可変変数は使い方によっては結構文字数減らせるので面白いです。

echoする際には""をのぞける場合もある

例えば下記のようなコードは、

echo "test";

このように書き直すことができます。

echo test;

これは、phpの未定義の定数を使用した際の挙動を利用したものです。

詳しくはこちらPHP: 構文 - Manual

可変関数を使う

可変変数の次は可変関数です。

こちらは複数回同じ関数を使う際に有効になります。

可変関数の詳しい説明はこちらPHP: 可変関数 - Manual

例えばこんな感じで同じ関数を使用するとき

echo implode($a);
echo implode($b);
echo implode($c);
echo implode($d);
echo implode($e);

可変関数を使うと結構文字数を削減できます。

$i=implode;
echo $i($a);
echo $i($b);
echo $i($c);
echo $i($d);
echo $i($e);

ただ、実際は同じ関数使う部分は極力一か所にまとめたりするので、可変関数は使う機会が限られるかもしれません。

phpのショートタグを使う

通常php

<?php echo "test";

というコードは、

<?="test";

というように書くことができます。

一番最初にforなどの制御構造が来てしまう場合は使うのは難しいですが、使える状況だと結構削れます。

終わりに

他にも色々あった気がするのですが、今のところぱっと思い出せるのがこれくらいなので、思い出し次第適宜追記していきたいと思います。

codegolfをやってみると、今まで知らなかった言語の仕様なども知れるので、初めて触る言語の勉強にもちょうどいいと思います。

ということで、一緒にcodegolfやりましょう

rubyの勉強始めました

個人的に気になった特徴

  • 末尾にセミコロン(;)が不要

文字出力(print, puts, p)

  • Objectを文字列として出力する
    • print
    • puts
      • 改行が付与される
    • p
      • デバッグ用に使われる
      • オブジェクトの形式を含め表示

# コード
array = ['test1','test2','test3']

print array
puts array
p array

# 出力結果
test1test2test3test1
test2
test3
["test1", "test2", "test3"]
  • 上記のようにputsでは配列の要素1つ1つに対して改行が付与されていることがわかる
    • ハッシュに対しては特に要素毎の改行はされなかった

配列

定義

array = ['test1','test2','test3']

# コード
array = ['test1','test2','test3']
p array[0]     # 0番目、つまりtest1
p array[-1]    # 後ろから1番目、つまりtest3
## 要素の呼び出しは範囲でも可能
p array[0..2]  # 0から2まで
p array[0...2] # 0から1まで(2を含まない)

# 出力結果
"test1"
"test3"
["test1", "test2", "test3"]
["test1", "test2"]

ハッシュ

定義

hash = {"test1" => 10, "test2" => 20, "test3" => 30}

キーにシンボルというものを使って、下記のように表記することも可能(文字列キーよりアクセスが早い)

hash_symbol = {:test1 => 10, :test2 => 20, :test3 => 30}

また、シンボルは次の様に省略して記述可能(ruby1.9からサポート)

hash_symbol2 = {test1: 10, test2: 20, test3: 30}

# code
hash = {"test1" => 10, "test2" => 20, "test3" => 30}
p hash
hash_symbol = {:test1 => 10, :test2 => 20, :test3 => 30}
p hash_symbol
hash_symbol2 = {test1: 10, test2: 20, test3: 30}
p hash_symbol2

# 出力結果
{"test1"=>10, "test2"=>20, "test3"=>30}
{:test1=>10, :test2=>20, :test3=>30}
{:test1=>10, :test2=>20, :test3=>30}
  • ruby2.2.4でpで出力すると省略して記述したものも、通常のシンボルでの表記で出力された

javascriptのコールバック関数

javascriptの勉強はじめました。

いきなりコールバック関数ってなんじゃこれという感じになったので、今わかってる範囲内でメモ。

下記のように、test1のcallback(‘aaa’, ‘bbb’)がtest2の引数a,bにそれぞれ渡される挙動をするのがコールバック関数。

function test1(callback) {
    callback('aaa', 'bbb');
}

function test2(a, b) {
    console.log(a + "," + b);
}

test1(test2);

使い所としては、非同期の場合に処理の順序を制御する場合など。

例えばこれだと出力はfugaとなり想定通りなものとなる。

function test1(hoge) {
    hoge = 'fuga';
    return hoge;
}

function test2(hoge) {
    console.log(hoge);
}

var hoge = 'hoge';
test2(test1(hoge));

出力:fuga

一方で非同期なため、下記のようにtest1で時間をかけてしまうとfugaに文字列がセットされる前にtest2が走ってしまいundefinedとなってしまう。

function test1(hoge) {
    setTimeout(function () {
        hoge = 'fuga';
        return hoge;
    }, 1000);
}

function test2(hoge) {
    console.log(hoge);
}

var hoge = 'hoge';
test2(test1(hoge));

出力:undefined

そこでコールバック関数を使って制御をしてあげるとちゃんと出力がfugaとなる。

function test1(callback) {
    var hoge = 'hoge';
    setTimeout(function () {
        hoge = 'fuga';
        callback(hoge)
    }, 1000);
}

function test2(hoge) {
    console.log(hoge);
}

test1(test2);

出力:fuga

それにしても、時間かけるようにするためsleep関数とかないかなーと思ったのですが、javascriptってsleep関数ないのですね……

docomo端末でのMVNOテザリング有効化方法

導入

だいぶ前に手に入れた0sim(0 SIM | nuroモバイル)を長らく放置していたので、余っていたDocomo端末にさしてモバイルルータ代わりにしました。

月500MBまでしか無料じゃないですけど、そこまで頻繁には使わないので中々快適です。

ただ、Docomo端末でMVNOを使ってテザリングする際に罠が一つあったのでここに書いておきます。

ちなみにメインで使ってるau端末はMVNO使ってますがテザリングはそのまま使えたのでdocomo端末特有の問題だと思われます。

どんな罠があるのか?

結論から言ってしまうと、Docomo端末でMVNO使ってテザリングするとネットに繋がりません。

これは、テザリングする際にDocomo端末はデフォルトのAPNを見にいってしまって、MVNO用に設定したAPNを見に行かないのが原因みたいです。

どうやってテザリング中にネット接続をできるようにするのか

まずはadb使えるように環境を整える必要があります。

自分はMac環境ですが、Android Studioを入れていたため既にadbが入っている状態でしたので、ここは省略

下記は実際に自分の持っている端末(Docomo L-05D)に対して行ったことです。

  1. PCでadbを使える環境を整える
  2. スマートフォンをUSBデバッグ状態でPCと接続する
  3. コマンドプロンプトやターミナルで下記コマンドを実行(L-05Dの場合)
$ adb shell content insert --uri content://settings/secure --bind name:s:tether_dun_required --bind value:i:0

–bind value:i:に0を指定することでテザリング時にAPNが変更されなくなります。

もとに戻したい時はここの0を1にすればOK。

PCとスマートフォンを接続するケーブルは給電専用ではなくて、下記のようなデータ通信可能なケーブルを使ってください

補足: adb contentコマンドの使い方

下記コマンドでcontentコマンドの使い方が見れる

$ adb shell content

出力結果

usage: adb shell content [subcommand] [options]

usage: adb shell content insert --uri <URI> --bind <BINDING> [--bind <BINDING>...]
  <URI> a content provider URI.
  <BINDING> binds a typed value to a column and is formatted:
  <COLUMN_NAME>:<TYPE>:<COLUMN_VALUE> where:
  <TYPE> specifies data type such as:
  b - boolean, s - string, i - integer, l - long, f - float, d - double
  Note: Omit the value for passing an empty string, e.g column:s:
  Example:
  # Add "new_setting" secure setting with value "new_value".
  adb shell content insert --uri content://settings/secure --bind name:s:new_setting --bind value:s:new_value

usage: adb shell content update --uri <URI> [--where <WHERE>]
  <WHERE> is a SQL style where clause in quotes (You have to escape single quotes - see example below).
  Example:
  # Change "new_setting" secure setting to "newer_value".
  adb shell content update --uri content://settings/secure --bind value:s:newer_value --where "name='new_setting'"

usage: adb shell content delete --uri <URI> --bind <BINDING> [--bind <BINDING>...] [--where <WHERE>]
  Example:
  # Remove "new_setting" secure setting.
  adb shell content delete --uri content://settings/secure --where "name='new_setting'"

usage: adb shell content query --uri <URI> [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>]
  <PROJECTION> is a list of colon separated column names and is formatted:
  <COLUMN_NAME>[:<COLUMN_NAME>...]
  <SORT_OREDER> is the order in which rows in the result should be sorted.
  Example:
  # Select "name" and "value" columns from secure settings where "name" is equal to "new_setting" and sort the result by name in ascending order.
  adb shell content query --uri content://settings/secure --projection name:value --where "name='new_setting'" --sort "name ASC"