#chiroito ’s blog

Java を中心とした趣味の技術について

JShell 自体をデバッグしてみた

Java Bug System を見ていたら JShell 自体のデバッグを見つけたので、パッチを書こうと思いJShellについて調べてみた。

使い方や 2 つの JVM が動くぐらいは知っていたけど、具体的には知らないので調べてみました。

試しにjshellコマンドを実行してからjmcjcmdを確認するとjdk.internal.jshell.tool.JShellToolProviderjdk.jshell.execution.RemoteExecutionControlが起動するのが確認できます。

人間がふれ合うクラスはjdk.internal.jshell.tool.JShellToolProviderです。

jdk.internal.jshell.tool.JShellToolProviderの実行時引数を確認したところ以下のような感じでした。

java -Dapplication.home=C:\Oracle\Java\jdk-11 -Xms8m -Djdk.module.main=jdk.jshell jdk.internal.jshell.tool.JShellToolProvider

これに-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:12345を付けてデバッグできるようにします。

全部付けるとこんな感じ。

java -Dapplication.home=C:\Oracle\Java\jdk-11 -Xms8m -Djdk.module.main=jdk.jshell -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:12345jdk.internal.jshell.tool.JShellToolProvider

デバッグが出来るようになりましたが、気になるのはユーザからの入力を待つ場所あたりかと。 これは、jdk.jshellモジュールの中ではjdk.internal.jshell.tool.ConsoleIOContextクラスのpublic String readLine(String prompt, String prefix) throws IOException, InputInterruptedExceptionメソッドでユーザの入力を待ちます。

@Override
public String readLine(String prompt, String prefix) throws IOException, InputInterruptedException {
(略)
  try {
    return in.readLine(prompt);
  } catch (UserInterruptException ex) {
(略)
}

inのオブジェクトはjdk.internal.leモジュールのjdk.internal.jline.console.ConsoleReaderです。 jdk.internal.leモジュールでは、jdk.internal.jline.internal.InputStreamReaderクラスのpublic int read(char[] buf, int offset, int length) throws IOExceptionメソッドでユーザの入力を待ちます。

@Override
public int read(char[] buf, int offset, int length) throws IOException {
(略)
  int off = bytes.arrayOffset() + bytes.limit();
  int was_red = in.read(bytes.array(), off, to_read);

  if (was_red == -1) {
(略)
}

Yumによるパッケージの自動更新を無効にしてみた

VirtualBox 上で動かしている Linux が yum のキャッシュのせいで時折ディスクフルになっていた。これまでは毎回yum clean allでキャッシュを消してたけど、根本原因を探ってみた。

yum-cronなるものがあると定期的にyumを実行するようだ。

# rpm -qa | grep yum
PackageKit-yum-1.1.5-1.0.1.el7.x86_64
yum-metadata-parser-1.1.4-10.el7.x86_64
yum-langpacks-0.4.2-7.el7.noarch
yum-utils-1.1.31-45.0.2.el7.noarch
yum-rhn-plugin-2.0.1-10.0.1.el7.noarch
yum-3.4.3-158.0.1.el7.noarch
yum-plugin-ulninfo-0.2-13.el7.noarch

とりあえず、インストールされていない。あても無いので一体誰が動いているのかを確認してみた。どうせyumという名前が付いているだろうと思ってpsgrepで検索。

# ps xl | grep yum
0     0  6379  5928  20   0 112732  2368 pipe_w S+   pts/1      0:00 grep --color=auto yum
0     0 18326  1678  20   0 460864 38376 poll_s S    ?          0:00 /usr/bin/python /usr/share/PackageKit/helpers/yum/yumBackend.py get-repo-list ~devel

# ps l -p 1678
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
4     0  1678     1  20   0 501848 27068 poll_s Ssl  ?          0:06 /usr/libexec/packagekitd

packagekitd というプロセスっぽい。とりあえず、systemctlで見てみたらあった。

# systemctl status packagekit
● packagekit.service - PackageKit Daemon
   Loaded: loaded (/usr/lib/systemd/system/packagekit.service; static; vendor preset: disabled)
   Active: active (running) since 火 2018-12-11 16:09:37 JST; 2 weeks 2 days ago
 Main PID: 1678 (packagekitd)
   CGroup: /system.slice/packagekit.service
           ├─ 1678 /usr/libexec/packagekitd
           └─18326 /usr/bin/python /usr/share/PackageKit/helpers/...

12月 14 08:33:46 localhost.localdomain PackageKit[1678]: update-...
12月 14 08:33:54 localhost.localdomain PackageKit[1678]: get-upd...
12月 14 08:33:54 localhost.localdomain PackageKit[1678]: get-upd...
12月 14 08:33:59 localhost.localdomain PackageKit[1678]: get-upd...
12月 14 08:34:00 localhost.localdomain PackageKit[1678]: get-upd...
12月 15 10:20:10 localhost.localdomain PackageKit[1678]: get-upd...
12月 28 15:22:51 localhost.localdomain PackageKit[1678]: get-upd...
12月 28 15:28:25 localhost.localdomain PackageKit[1678]: get-upd...
12月 28 15:38:26 localhost.localdomain PackageKit[1678]: get-upd...
12月 28 15:48:28 localhost.localdomain PackageKit[1678]: resolve...
Hint: Some lines were ellipsized, use -l to show in full.

元気に動いているようなので、止めて、二度と起動しないようにする。

# systemctl stop packagekit
# systemctl disable packagekit
# systemctl status packagekit
● packagekit.service - PackageKit Daemon
   Loaded: loaded (/usr/lib/systemd/system/packagekit.service; static; vendor preset: disabled)
   Active: inactive (dead)

12月 14 08:33:54 localhost.localdomain PackageKit[1678]: get-upd...
12月 14 08:33:59 localhost.localdomain PackageKit[1678]: get-upd...
12月 14 08:34:00 localhost.localdomain PackageKit[1678]: get-upd...
12月 15 10:20:10 localhost.localdomain PackageKit[1678]: get-upd...
12月 28 15:22:51 localhost.localdomain PackageKit[1678]: get-upd...
12月 28 15:28:25 localhost.localdomain PackageKit[1678]: get-upd...
12月 28 15:38:26 localhost.localdomain PackageKit[1678]: get-upd...
12月 28 15:48:28 localhost.localdomain PackageKit[1678]: resolve...
12月 28 15:56:10 localhost.localdomain systemd[1]: Stopping Pack...
12月 28 15:56:10 localhost.localdomain systemd[1]: Stopped Packa...
Hint: Some lines were ellipsized, use -l to show in full.

Terraform で Oracle Cloud Infrastructure を構築する

Terraform を使って以下のような構成の Oracle Cloud Infrastructure を構築してみました。

f:id:chiroito:20181228142831p:plain
Terraform で作成する環境

設定を以下の 4 つに分けて紹介します。

  • パラメータ
  • OCI プロバイダの設定
  • インフラの設定
  • インスタンスの設定

パラメータは terraform.auto.tfvars、設定は 1 つのファイルにまとめて terraform.tf など適当なファイル名を付けて同じディレクトリへ保存して下さい。

そのディレクトリで以下のようにすると環境が作られます。

terraform init
terraform apply

参考

パラメータ

tenancy_ocid="ocid1.tenancy.oc1..xxxxxx(略)xxxx"
user_ocid="ocid1.user.oc1..xxxx(略)xxxxxxx"
parrent_compartment_ocid="ocid1.compartment.oc1..xxxx(略)xxxxxxx"
fingerprint="xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
private_key_path="C:\\Users\\chito\\.oci\\oci_api_key.pem"
region="us-phoenix-1"
environment_name="test"
environment_description="検証用の環境"
domain_name="各自のドメイン"
instance_shape="VM.Standard2.1"
ssh_public_key="ssh-rsa xxxxxx(略)xxxxxx== rsa-key-20181124"

OCI プロバイダの設定

# OCIプロバイダのための変数
variable "region" {}
variable "tenancy_ocid" {}
variable "user_ocid" {}
variable "fingerprint" {}
variable "private_key_path" {}

# OCI プロバイダの設定
provider "oci" {
  region = "${var.region}"
  tenancy_ocid = "${var.tenancy_ocid}"
  user_ocid = "${var.user_ocid}"
  fingerprint = "${var.fingerprint}"
  private_key_path = "${var.private_key_path}"
}

インフラの設定

# ネットワークなどの基盤のための変数
variable "parrent_compartment_ocid" {}
variable "environment_name" {}
variable "environment_description" {}
variable "domain_name" {}

# 既存のコンパートメントの下に新しいコンパートメントを作成
resource "oci_identity_compartment" "target_compartment" {
  name = "${var.environment_name}"
  description = "${var.environment_description}"
  compartment_id = "${var.parrent_compartment_ocid}"
}

# 仮想クラウドネットワーク
resource "oci_core_vcn" "target_vcn" {
  cidr_block = "10.0.0.0/16"
  compartment_id = "${oci_identity_compartment.target_compartment.id}"
  dns_label = "${var.environment_name}"
}

# インターネットゲートウェイ
resource "oci_core_internet_gateway" "ig" {
  compartment_id = "${oci_identity_compartment.target_compartment.id}"
  vcn_id = "${oci_core_vcn.target_vcn.id}"
}

# デフォルトルートテーブルを修正
resource "oci_core_default_route_table" "default-route-table" {
  manage_default_resource_id = "${oci_core_vcn.target_vcn.default_route_table_id}"

  route_rules {
    destination = "0.0.0.0/0"
    destination_type = "CIDR_BLOCK"
    network_entity_id = "${oci_core_internet_gateway.ig.id}"
  }
}

# デフォルトDHCPオプションを修正
resource "oci_core_default_dhcp_options" "default-dhcp-options" {
  manage_default_resource_id = "${oci_core_vcn.target_vcn.default_dhcp_options_id}"

  options {
    type = "DomainNameServer"
    server_type = "VcnLocalPlusInternet"
  }
  options {
    type = "SearchDomain"
    search_domain_names = [
      "${var.domain_name}"]
  }
}

# デフォルトセキュリティリストを修正
resource "oci_core_default_security_list" "default-security-list" {
  manage_default_resource_id = "${oci_core_vcn.target_vcn.default_security_list_id}"

  egress_security_rules {
    destination = "0.0.0.0/0"
    protocol = "6"
    tcp_options {
      "min" = 80
      "max" = 80
    }
  }

  egress_security_rules {
    destination = "0.0.0.0/0"
    protocol = "6"
    tcp_options {
      "min" = 443
      "max" = 443
    }
  }

  ingress_security_rules {
    protocol = "6"
    source = "0.0.0.0/0"
    tcp_options {
      "min" = 22
      "max" = 22
    }
  }

  ingress_security_rules {
    protocol = 1
    source = "0.0.0.0/0"
    stateless = true
    icmp_options {
      "type" = 3
      "code" = 4
    }
  }
}

# AD1にサブネットを作る
resource "oci_core_subnet" "ad_subnet" {
  compartment_id = "${oci_identity_compartment.target_compartment.id}"
  vcn_id = "${oci_core_vcn.target_vcn.id}"
  availability_domain = "${lookup(data.oci_identity_availability_domains.ads.availability_domains[0], "name")}"
  dns_label = "ad1"
  cidr_block = "10.0.1.0/24"
}

# 利用可能な Availability Domain の一覧を取得する
data "oci_identity_availability_domains" "ads" {
  compartment_id = "${var.parrent_compartment_ocid}"
}

インスタンスの設定

# インスタンスのための変数
variable "instance_shape" {}
variable "ssh_public_key" {}

# リージョン毎のOracle Linux 7.6 のイメージの OCID
variable "instance_image_ocid" {
  type = "map"

  default = {
    // 各イメージのOCIDは https://docs.us-phoenix-1.oraclecloud.com/images/ を参照下さい
    // 今回は Oracle が提供している "Oracle-Linux-7.6-2018.11.19-0" イメージを使用します
    eu-frankfurt-1 = "ocid1.image.oc1.eu-frankfurt-1.aaaaaaaa2rvnnmdz6ewn4pozatb2l6sjtpqpbgiqrilfh3b4ee7salrwy3kq"
    us-ashburn-1 = "ocid1.image.oc1.iad.aaaaaaaa2mnepqp7wn3ej2axm2nkoxwwcdwf7uc246tcltg4li67z6mktdiq"
    uk-london-1 = "ocid1.image.oc1.uk-london-1.aaaaaaaaikjrglbnzkvlkiltzobfvtxmqctoho3tmdcwopnqnoolmwbsk3za"
    us-phoenix-1 = "ocid1.image.oc1.phx.aaaaaaaaaujbtv32uv4mizzbgnjkjlvbeaiqj5sgc6r5umfunebt7qpzdzmq"
  }
}

resource "oci_core_instance" "instance1" {
  count = "1"
  availability_domain = "${oci_core_subnet.ad_subnet.availability_domain}"
  compartment_id = "${oci_identity_compartment.target_compartment.id}"
  shape = "${var.instance_shape}"
  fault_domain = "FAULT-DOMAIN-1"
  create_vnic_details {
    subnet_id = "${oci_core_subnet.ad_subnet.id}"
    assign_public_ip = true
  }
  source_details {
    source_type = "image"
    source_id = "${var.instance_image_ocid[var.region]}"
  }
  metadata {
    ssh_authorized_keys = "${var.ssh_public_key}"
  }
}