Hyper-V上のUbuntuにLIS(Linux Integration Services)をインストールする。

UbuntuをHyper-Vで実行していると遅いなと感じる場合はMicrosoftが提供するLinux Integration Services(LIS)をインストールすると改善する可能性があります。

最初に、 /etc/initramfs-tools/modules に次の行を追加します。

$ sudo vi /etc/initramfs-tools/modules
hv_vmbus   # 追加
hv_storvsc # 追加
hv_blkvsc  # 追加
hv_netvsc  # 追加

次のコマンドを実行して modules ファイルを再初期化し、仮想ツールをインストールしてマシンを再起動します。

$ sudo apt install linux-virtual linux-cloud-tools-virtual linux-tools-virtual
$ sudo update-initramfs -u
$ sudo reboot

再起動されると、LISがシステムに登録されます。 インストールされているかを確認するには、ターミナルでlsmodを実行し、hid_hyperv、hv_netvsc、hv_utils、hv_storvc、hv_vmbus が存在する場合、LISのインストールは成功しています。

Docker for Windows を WSLで使う

Docker for Windowsをインストールする

 まずは、Docker for Windowsをインストールします。
 インストールが終わったら、画面右下のシステムトレイにあるDockerアイコンから設定画面を開きます。

 下記項目にチェックを入れて、TLSなしでデーモンに接続できるようにします。
 これにより、ローカルのWSLインスタンスが、Docker for Windows内で実行されているDockerデーモンに接続できるようになります。 デーモンはlocalhostにのみバインドされているため、ネットワーク上の他のマシンは接続できません。

Dockerのインストール

Docker公式HPに記載のあるとおりDockerをインストールします。

$ sudo apt update
$ sudo apt install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io

docker-composeもインストールします。

$ sudo curl -L https://github.com/docker/compose/releases/download/1.25.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

sudoしなくてもdockerコマンドを実行できるようにdockerグループにユーザーを追加します。

$ sudo usermod -aG docker $USER

Docker for Windowsに接続するために以下の設定を.bashrcに追加します。

$ echo "export DOCKER_HOST=tcp://localhost:2375" >> ~/.bashrc && source ~/.bashrc 

dockerが動くようになっていることを確認します。

$ docker info
$ docker-compose --version

ボリュームマウントのための設定

WSL上ではドライブは /mnt/d にマウントされるのに対して、Docker for Windowsでは内部で /d にマウントされているため、そのままで空のボリュームをマウントしてしまいます。

この対策として、/etc/wsl.conf に root=/ の設定を追加することで /mnt ではなく / にマウントされるようになります。

$ vi /etc/wsl.conf
[automount]
root = /
options = "metadata,umask=22,fmask=11"

設定した後、一旦ログアウト/ログインするか、以下のコマンドをコマンドプロンプトで実行してWSLを再起動すると / に各ドライブがマウントされるようになります。

C:\> net stop LxssManager
LxssManager サービスを停止中です.
LxssManager サービスは正常に停止されました。
C:\> net start LxssManager
LxssManager サービスを開始します.
LxssManager サービスは正常に開始されました。 

また、別の方法として、/mnt/d を /d にマウントする方法があります。

$ sudo mkdir /d
$ sudo mount –bind /mnt/d /d

ただし、この方法だと.bashrcに以下のようにコマンドを追加しておく必要があります。

$ echo "sudo mount --bind /mnt/c /c" >> ~/.bashrc && source ~/.bashrc

$ # パスワードなしでマウント出来るようにしたい場合は以下の設定を追加する
$ sudo visudo
$ username ALL=(root) NOPASSWD: /bin/mount

Kubernetes 1.17にしたら起動しなくなった時

Kubernetesのパッケージを一部ホールド(apt-mark hold)し忘れて1.17にアップグレードしちゃいました。そしたら、Nodeが起動しなくなっちゃいました。

$ kubectl get node
NAME      STATUS     ROLES    AGE   VERSION
testvm1   NotReady   master   46d   v1.17.0

kubectl describeでノードの状態を調べると以下のようなログが出てました。

$ kubectl describe node testvm1
略
 Failed to initialize CSINodeInfo: error updating CSINode annotation:  timed out waiting for the condition; caused by: the server could not  find the requested resource 
“Kubernetes 1.17にしたら起動しなくなった時” の続きを読む

複数のm2tsファイルを結合して1つにする方法

以下のようにMPEG ts(トランスポートストリーム)ファイルを結合するだけで結合できると思います。

 $ cat file1.m2ts file2.m2ts file3.m2ts > output.m2ts

しかし、 前述のcatでの結合は一般的に機能しますが、タイムコードの問題により、一部のメディアプレーヤーで問題が発生する可能性があります。

“複数のm2tsファイルを結合して1つにする方法” の続きを読む

Windows10(WSL)にHomebrewを入れる

WSLには開発用ツールが入っていませんので、まずはbuild-essentialをインストールします(あとでもいいかも?)。
$ sudo apt install build-essential

Homebrewの公式HPにも記載のある次のコマンドを実行します。

$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"

次の変数を~/.profileに追加します。

export HOMEBREW_PREFIX="/home/linuxbrew/.linuxbrew"
export HOMEBREW_CELLAR="/home/linuxbrew/.linuxbrew/Cellar"
export HOMEBREW_REPOSITORY="/home/linuxbrew/.linuxbrew/Homebrew"
export PATH="/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:$PATH"
export MANPATH="/home/linuxbrew/.linuxbrew/share/man:$MANPATH"
export INFOPATH="/home/linuxbrew/.linuxbrew/share/info:$INFOPATH"

[Kotlin] JavaからKotlinを呼び出す

※翻訳がわかりにくい場合は原文を読んでください。

KotlinコードはJavaから簡単に呼び出すことができます。

プロパティ

Kotlinプロパティは、次のJava要素にコンパイルされます。

  • get接頭辞を前置することによって計算された名前を持つgetterメソッド
  • set接頭辞を前置することによって計算された名前を持つsetterメソッド(varプロパティに対してのみ)
  • プロパティ名と同じ名前のプライベートフィールド(バッキングフィールドを持つプロパティのみ)

例えば、 var firstName: String は以下のJava宣言にコンパイルされます

private String firstName;

public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

プロパティの名前が isで始まる場合、別の名前マッピング規則が使用されます。ゲッターの名前は次のようになります。 プロパティ名と同じで、setterの名前は issetに置き換えることで得られます。 たとえば、プロパティisOpenの場合、getterはisOpen()と呼ばれ、setterはsetOpen()と呼ばれます。 このルールは、 Booleanだけでなくあらゆるタイプのプロパティに適用されます。

パッケージレベルの関数

拡張機能を含む org.foo.barパッケージ内のexample.ktファイル内で宣言されたすべての関数とプロパティは、 org.foo.bar.ExampleKt`という名前のJavaクラスの静的メソッドにコンパイルされます。

// example.kt
package demo

class Foo

fun bar() {
}
// Java
new demo.Foo();
demo.ExampleKt.bar();

生成されたJavaクラスの名前は、 @JvmNameアノテーションを使用して変更できます。

@file:JvmName("DemoUtils")

package demo

class Foo

fun bar() {
}
// Java
new demo.Foo();
demo.DemoUtils.bar();

生成された同じJavaクラス名を持つ複数のファイルを持つ(同じパッケージで同じ名前または同じ @JvmNameアノテーション)は通常エラーです。 ただし、コンパイラには、指定された名前を持ち、その名前を持つすべてのファイルのすべての宣言が含まれる単一のJavaファサードクラスを生成する機能があります。 このようなファサードの生成を可能にするには、すべてのファイルで@JvmMultifileClassアノテーションを使用します。

// oldutils.kt
@file:JvmName("Utils")
@file:JvmMultifileClass

package demo

fun foo() {
}
// newutils.kt
@file:JvmName("Utils")
@file:JvmMultifileClass

package demo

fun bar() {
}
// Java
demo.Utils.foo();
demo.Utils.bar();

インスタンスフィールド

JavaのフィールドとしてKotlinプロパティを公開する必要がある場合は、それを @JvmFieldアノテーションでアノテートする必要があります。 フィールドは、基になるプロパティと同じ可視性を持ちます。 @JvmFieldにバッキングフィールドがある、プライベートでない、 openoverrideconst修飾子を持たず、委譲されたプロパティでない場合、プロパティに注釈を付けることができます。

class C(id: String) {
    @JvmField val ID = id
}
// Java
class JavaClient {
    public String getID(C c) {
        return c.ID;
    }
}

Late-Initialized プロパティもフィールドとして公開されます。 フィールドの可視性は、 lateinitプロパティーセッターの可視性と同じになります。

静的フィールド

名前付きオブジェクトまたはコンパニオンオブジェクトで宣言されたKotlinプロパティは、名前付きオブジェクトまたはコンパニオンオブジェクトを含むクラスの静的なバッキングフィールドを持ちます。

通常、これらのフィールドはプライベートですが、次のいずれかの方法で公開することができます。

  • @JvmField アノテーション
  • lateinit 修飾子
  • const 修飾子

このようなプロパティに @JvmFieldを付けると、プロパティ自体と同じ可視性を持つ静的フィールドになります。

class Key(val value: Int) {
    companion object {
        @JvmField
        val COMPARATOR: Comparator<Key> = compareBy<Key> { it.value }
    }
}
// Java
Key.COMPARATOR.compare(key1, key2);
// public static final field in Key class

オブジェクトまたはコンパニオンオブジェクトの late-initialized プロパティはプロパティセッターと同じ可視性を持つ静的なバッキングフィールドを持っています。

object Singleton {
    lateinit var provider: Provider
}
// Java
Singleton.provider = new Provider();
// public static non-final field in Singleton class

constでアノテーションされたプロパティ(クラス内とトップレベル)は、Javaの静的フィールドに変換されます

// file example.kt

object Obj {
    const val CONST = 1
}

class C {
    companion object {
        const val VERSION = 9
    }
}

const val MAX = 239

Javaの場合:

int c = Obj.CONST;
int d = ExampleKt.MAX;
int v = C.VERSION;

静的メソッド

前述のように、Kotlinは静的メソッドとしてパッケージレベルの関数を表します。 これらの関数に @JvmStaticと注釈を付けると、Kotlinは名前付きオブジェクトやコンパニオンオブジェクトで定義された関数の静的メソッドを生成することもできます。 このアノテーションを使用すると、コンパイラはオブジェクトの囲むクラスに静的メソッドを生成し、オブジェクト自体にインスタンスメソッドを生成します。 例えば、

class C {
    companion object {
        @JvmStatic fun foo() {}
        fun bar() {}
    }
}

今、 foo()はJavaでは静的ですが、 bar()は静的ではありません

C.foo(); // works fine
C.bar(); // error: not a static method
C.Companion.foo(); // instance method remains
C.Companion.bar(); // the only way it works

名前付きオブジェクトと同じ

object Obj {
    @JvmStatic fun foo() {}
    fun bar() {}
}

Javaの場合:

Obj.foo(); // works fine
Obj.bar(); // error
Obj.INSTANCE.bar(); // works, a call through the singleton instance
Obj.INSTANCE.foo(); // works too

@JvmStaticアノテーションは、オブジェクトまたはコンパニオンオブジェクトのプロパティに適用することもできます。そのため、getterメソッドとsetterメソッドは、そのオブジェクトまたはコンパニオンオブジェクトを含むクラスの静的メンバになります。

## 可視性

Kotlinの可視性は、次のようにJavaにマッピングされます。

  • privateメンバはprivateメンバにコンパイルされます。
  • privateトップレベル宣言はパッケージローカル宣言にコンパイルされます。
  • protectedprotectedのままです(Javaは同じパッケージ内の他のクラスから保護されたメンバーにアクセスすることができます Kotlinはそうしないので、Javaクラスはコードへのより広いアクセスを持つでしょう)。
  • internal宣言はJavaでpublicになります。 internalクラスのメンバは、誤ってJavaからそれらを使用するのを困難にし、Kotlinの規則に従ってお互いに見えない同じ署名を持つメンバのためにオーバーロードを許容するために、名前修飾を受けます。
  • publicpublicのままです。

## Kクラス

時々 KClass型のパラメータでKotlinメソッドを呼び出す必要があります。 ClassからKClassへの自動変換はありませんので、 Class <T> .kotlin拡張プロパティと同等のものを呼び出すことで手動で行う必要があります:

kotlin.jvm.JvmClassMappingKt.getKotlinClass(MainView.class)

@JvmNameで署名の衝突を処理する

Kotlinには、バイトコードとは異なるJVM名が必要な名前付き関数があります。 最も顕著な例は型消去のために起こります。

fun List<String>.filterValid(): List<String>
fun List<Int>.filterValid(): List<Int>

これら2つの関数は、JVMのシグネチャが同じ filterValid(Ljava/util/List;)Ljava/util/List; であるため、並行して定義することはできません。 Kotlinに同じ名前をつけたいのであれば、そのうちの1つ(または両方)に @JvmNameを付けて、別の名前を引数として指定することができます。

fun List<String>.filterValid(): List<String>

@JvmName("filterValidInt")
fun List<Int>.filterValid(): List<Int>

Kotlinからは filterValidと同じ名前でアクセスできますが、JavaからはfilterValidfilterValidIntがあります。

同じトリックが、 getX()関数の横にプロパティ xを持つ必要があるときに適用されます。

val x: Int
    @JvmName("getX_prop")
    get() = 15

fun getX() = 10

オーバーロード生成

通常、デフォルトのパラメータ値を持つKotlin関数を記述すると、Javaでは完全なシグネチャとしてのみ表示され、すべてのパラメータが表示されます。複数のオーバーロードをJava呼び出し側に公開する場合は、 @JvmOverloadsアノテーションを使用できます。

注釈は、コンストラクタ、静的メソッドなどにも使用できます。インタフェースで定義されたメソッドを含む抽象メソッドでは使用できません。

class Foo @JvmOverloads constructor(x: Int, y: Double = 0.0) {
    @JvmOverloads fun f(a: String, b: Int = 0, c: String = "abc") {
        ...
    }
}

デフォルト値を持つすべてのパラメータについて、これは追加のオーバーロードを1つ生成します。このオーバーロードには、このパラメータがあり、パラメータリストのその右側のすべてのパラメータが削除されます。この例では、次のものが生成されます。

// Constructors:
Foo(int x, double y)
Foo(int x)

// Methods
void f(String a, int b, String c) { }
void f(String a, int b) { }
void f(String a) { }

Secondary Constructorsで説明されているように、クラスにすべてのコンストラクタパラメータのデフォルト値がある場合は、引数なしのpublicコンストラクタが生成されます。これは、@JvmOverloadsアノテーションが指定されていなくても機能します。

チェックされた例外

上記のように、Kotlinは例外をチェックしていません。 したがって、通常、Kotlin関数のJavaシグネチャは例外がスローされたことを宣言しません。 したがって、Kotlinに次のような関数があるとします。

// example.kt
package demo

fun foo() {
    throw IOException()
}

そして、Javaから呼び出して例外をキャッチしたい

// Java
try {
  demo.Example.foo();
}
catch (IOException e) { // error: foo() does not declare IOException in the throws list
  // ...
}

foo()IOExceptionを宣言しないので、Javaコンパイラからエラーメッセージが出ます。 この問題を回避するには、Kotlinで @Throwsアノテーションを使用してください。

@Throws(IOException::class)
fun foo() {
    throw IOException()
}

Null-safety

JavaからKotlin関数を呼び出すときに、null以外のパラメータとして null{: .keyword } を渡すことができなくなります。 だからこそ、Kotlinは、非nullを期待するすべてのパブリック関数のランタイムチェックを生成します。 このようにして、Javaコードで即座に NullPointerExceptionを取得します。

バリアントジェネリックス

Kotlinクラスが 宣言サイトの分散 を利用する場合、 その使用法がJavaコードからどのように見えるかという2つのオプションがあります。次のクラスとそれを使用する2つの関数があるとしましょう。

class Box<out T>(val value: T)

interface Base
class Derived : Base

fun boxDerived(value: Derived): Box<Derived> = Box(value)
fun unboxBase(box: Box<Base>): Base = box.value

これらの関数をJavaに変換する素朴な方法は次のとおりです。

Box<Derived> boxDerived(Derived value) { ... }
Base unboxBase(Box<Base> box) { ... }

問題は、Kotlinでは unboxBase(boxDerived("s")) と言うことができますが、Javaでは不可能です。なぜなら、JavaではクラスBoxはパラメータT不変であるため、従って Box<Derived>Box<Base> のサブタイプではありません。 Javaで動作させるには、次のように unboxBaseを定義する必要があります。

Base unboxBase(Box<? extends Base> box) { ... }  

ここでは、Javaのワイルドカード型? extends Base)を使用して、使用サイトの分散によって宣言サイトの分散をエミュレートします。なぜなら、それはJavaが持つすべてのものだからです。

Kotlin APIをJavaで動作させるために、パラメータとして現れるときに、共変に定義された Box(反逆的に定義されたFooの場合は Foo<? super Bar>)のBox<Super>Box<? extends Super>として生成します。戻り値の場合、ワイルドカードは生成されません。そうしなければ、Javaクライアントは対処する必要があります(一般的なJavaコーディングスタイルに反します)。したがって、この例の関数は実際には次のように変換されます。

// return type - no wildcards
Box<Derived> boxDerived(Derived value) { ... }

// parameter - wildcards 
Base unboxBase(Box<? extends Base> box) { ... }

注意:引数の型がfinalの場合、通常はワイルドカードを生成する点はないので、どの位置にあっても Box <String>は常に Box <String>です。

デフォルトで生成されないワイルドカードが必要な場合は、 @JvmWildcardアノテーションを使用できます。

fun boxDerived(value: Derived): Box<@JvmWildcard Derived> = Box(value)
// is translated to 
// Box boxDerived(Derived value) { ... }

一方、生成されるワイルドカードが必要ない場合は、 @ JvmSuppressWildcardsを使用することができます。

fun unboxBase(box: Box<@JvmSuppressWildcards Base>): Base = box.value
// is translated to 
// Base unboxBase(Box<Base> box) { ... }

注意: @JvmSuppressWildcardsは、個々の型引数だけでなく、関数やクラスなどの宣言全体でも使用でき、その中のすべてのワイルドカードを抑止できます。

Nothing型の翻訳

Nothing は、Javaに自然な対応がないため特別です。 実際、 java.lang.Voidを含むすべてのJava参照型は値としてnullを受け取り、 Nothingはそれを受け入れません。したがって、このタイプはJavaの世界では正確に表現できません。 これがKotlinが Nothing型の引数が使われる生の型を生成する理由です:

fun emptyList(): List<Nothing> = listOf()
// is translated to
// List emptyList() { ... }

[Swift] GCD関連 [Swift4対応]

  • キューの作成

(Swift2まで)

let queue1 = dispatch_queue_create("arrayQ", DISPATCH_QUEUE_SERIAL)
let queue2 = dispatch_queue_create("arrayQ", DISPATCH_QUEUE_CONCURRENT)

(Swift3以降)

let queue1 = DispatchQueue(label: "arrayQ")
let queue2= DispatchQueue(label: "arrayQ", attributes: .concurrent)

(Swift2まで)

let queue3 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)
let queue4 = dispatch_get_main_queue()

(Swift3以降)

let queue3 = DispatchQueue.global(qos:DispatchQoS.QoSClass.background)
let queue4= DispatchQueue.main
  • グループの作成

(Swift2まで)

let group = dispatch_group_create()

(Swift3以降)

let group = DispatchGroup()
  • グループのwait

(Swift2まで)

dispatch_group_wait(group, dispatch_time_t(DISPATCH_TIME_FOREVER))

(Swift3以降)

group.wait(wallTimeout: .distantFuture)
  • 同期処理

(Swift2まで)

dispatch_sync(queue, {() in
...
}

(Swift3以降)

queue.sync {() in
...
}
  • 非同期処理

(Swift2まで)

dispatch_async(queue, {() in
...
}

(Swift3以降)

queue.async {() in
...
}

(Swift2まで)

dispatch_barrier_async(queue, {() in
...
}

(Swift3以降)

queue.async(flags: .barrier) {() in
...
}
  • セマフォ宣言

(Swift2まで)

let semaphore:dispatch_semaphore_t

(Swift3以降)

let semaphore:DispatchSemaphore
  • セマフォの作成

(Swift2まで)

semaphore = dispatch_semaphore_create(Int)

(Swift3以降)

semaphore = DispatchSemaphore(value: Int)
  • セマフォのwait

(Swift2まで)

if (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) == 0) {
...
}

(Swift3以降)

if (semaphore.wait(timeout:.distantFuture) == .success) {
...
}
  • セマフォのsignal

(Swift2まで)

dispatch_semaphore_signal(semaphore)

(Swift3以降)

semaphore.signal()

[Swift][Error]Argument labels ‘(_:)’ do not match any available overloads

・エラーメッセージ
Argument labels ‘(_:)’ do not match any available overloads

・エラー例

let num = 3
var nsnum = NSNumber(num)
// => Argument labels ‘(_:)’ do not match any available overloads


・原因
メソッドに必要なラベルが存在しないために発生します

“[Swift][Error]Argument labels ‘(_:)’ do not match any available overloads” の続きを読む

Macのsedで改行を出力する

Macのsedで特定の文字を改行に変換したいと思ったことがあると思いますが、Macでは ‘\n’ が出力できません。

$ echo "pen#apple#pen#pineapple" | sed 's/#/\n/g'
pennapplenpennpineapple

こんな感じのことをすれば出力できるようなのですが面倒です。

ってことで、

“Macのsedで改行を出力する” の続きを読む