あきろぐ

いろいろめもするよ🐈🐈🐈

【めも】csvファイルを良い感じに整形・結合して使いやすくしたい

何をしたいのか

アイテム名と値が別々のcsvファイルに吐き出されているので、2つのファイルを整形し1つのファイルにします。sedコマンドでファイルの整形できるけど、アイテム名-値が横に並ぶように結合するときに使えるコマンドあったかなと思い調べたのでそのメモです。

どうしたのか

  • sedコマンドでカンマを改行に変換する

出力されたcsvファイルは以下のような感じです。1行分が1回分のデータです。
f:id:akngo22:20190707002104p:plain

一番最新のデータを取得した後、カンマを改行に変換してファイルに出力します。

#2つのファイルをそれぞれ変換する
tail -1 item.csv | sed -e 's/,/\n/g' > item.txt
tail -1 data.csv  | sed -e 's/,/\n/g' > data.txt
  • pasteコマンドで2つのファイルを横に結合する
paste item.txt data.txt > item_data.txt

結果

こんな感じでアイテム名と値が横に並び見やすくなりました。

$ cat item_data.txt
item    1
item    1
item    1
item    1
item    1

番外編

pasteコマンドで-sオプションを使えば行と列を入れ替えることができます。

$ paste -s item.txt data.txt > item_data2.txt
$cat item_data2.txt
item    item    item    item    item    item    item    item    item    item    item    item    item    item    item    item    item    item    item    item    item    item    item    item    item    item
1       1       1       1       1       1       1       1       1       1       1       1       1       1       1       1       1       1       1       1       1       1       1       1       1       1

おわり

Elasticsearchが立ち上がらないときの対処法

どんなエラーが発生したのか?

Elasticsearchを起動させようとすると失敗する。

$ sudo systemctl start elasticsearch
● elasticsearch.service - Elasticsearch
   Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Sun 2019-06-09 06:41:29 UTC; 6min ago
     Docs: http://www.elastic.co
  Process: 5538 ExecStart=/usr/share/elasticsearch/bin/elasticsearch -p ${PID_DIR}/elasticsearch.pid --quiet -Edefault.path.logs=${LOG_DIR} -Edefault.path.data=${DATA_DIR} -Edefault.path.conf=${CONF_DIR} (code=exited, status=1/FAILURE)
  Process: 5537 ExecStartPre=/usr/share/elasticsearch/bin/elasticsearch-systemd-pre-exec (code=exited, status=0/SUCCESS)
 Main PID: 5538 (code=exited, status=1/FAILURE)

環境

  • Elasticsearch5.6
  • vagrant2.2.3
  • CentOS7.6

対処法

Elasticsearchのステータスの詳細を表示

上記の情報だけではよく分からないので、どこで失敗しているか詳細を見てみます。

$sudo systemctl status elasticsearch -l
[中略] 
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x0000000085330000, 2060255232, 0) failed; error='Cannot allocate memory' (errno=12)
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: #
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: # There is insufficient memory for the Java Runtime Environment to continue.
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: # Native memory allocation (mmap) failed to map 2060255232 bytes for committing reserved memory.
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: # An error report file with more information is saved as:
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: # /tmp/hs_err_pid5538.log
Jun 09 06:41:29 localhost.localdomain systemd[1]: elasticsearch.service: main process exited, code=exited, status=1/FAILURE
Jun 09 06:41:29 localhost.localdomain systemd[1]: Unit elasticsearch.service entered failed state.
Jun 09 06:41:29 localhost.localdomain systemd[1]: elasticsearch.service failed.

Javaを起動するために必要なメモリが不十分であることが判明。

Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x0000000085330000, 2060255232, 0) failed; error='Cannot allocate memory' (errno=12)
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: #
Jun 09 06:41:28 localhost.localdomain elasticsearch[5538]: # There is insufficient memory for the Java Runtime Environment to continue.

今回使用しているVMの搭載メモリは4GBでElasticsearchには2GB割り当てるように設定していたのですが、そんなに空きがなかったことが起動に失敗する原因でした。

設定ファイルの修正

Elasticsearchの割り当てメモリの変更(ヒープサイズ)は、"/etc/elasticesearch/jvm.options"で行います。
XmsとXmxの値を2GBから1GBに書き換えました。

$sudo vi /etc/elasticesearch/jvm.options
# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space

-Xms1g
-Xmx1g

公式ドキュメントにも記載がありますが、Xms(最小ヒープサイズ)とXmx(最大ヒープサイズ)は等しい値にする必要があります。詳しくは以下を参照してください。
www.elastic.co

Elasticsearchを再起動させる

設定ができたら、Elasticsearchを再起動させてステータスを確認します。ステータスがactiveになっていたらOKです。

$sudo systemctl restart elasticsearch
$systemctl status elasticsearch
● elasticsearch.service - Elasticsearch
   Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2019-06-09 06:53:47 UTC; 13s ago
     Docs: http://www.elastic.co
  Process: 6279 ExecStartPre=/usr/share/elasticsearch/bin/elasticsearch-systemd-pre-exec (code=exited, status=0/SUCCESS)
 Main PID: 6280 (java)
   CGroup: /system.slice/elasticsearch.service
           mq6280 /bin/java -Xms1g -Xmx1g -XX:+UseConcMarkSweepGC -XX:CMSInit...

Jun 09 06:53:47 localhost.localdomain systemd[1]: Starting Elasticsearch...
Jun 09 06:53:47 localhost.localdomain systemd[1]: Started Elasticsearch.
Jun 09 06:53:47 localhost.localdomain elasticsearch[6280]: OpenJDK 64-Bit Ser...
Hint: Some lines were ellipsized, use -l to show in full. 

動作確認

これでElasticsearchは正常に使えるはずなので、curlコマンドを使ってElasticsearchからレスポンス返ってくるか確認します。

$ curl http://0.0.0.0:9200
{
  "name" : "WTDjnDZ",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "f_ZGcQzRQGyhlqOA8XLVOA",
  "version" : {
    "number" : "5.6.16",
    "build_hash" : "3a740d1",
    "build_date" : "2019-03-13T15:33:36.565Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.1"
  },
  "tagline" : "You Know, for Search"

今回は、elasticsearchのymlファイルにて"network.host"を"0.0.0.0"に設定しているので、curl先は0.0.0.0にしています。ローカルホストを指定している場合は、"curl localhost:9200"でレスポンス返ってくるはずです。

curlを実行して以下のようなコネクションエラーが発生した場合は、"/etc/elasticsearch/elasticsearch.yml"ファイルのnetwork.hostを確認してください。

curl: (7) Failed connect to localhost:9200; Connection refused

以上です。

Zabbixエージェントによる監視が有効にならないときの対処法

エラー内容

ZabbixのWebインターフェース画面を確認すると、登録したホストに以下のエラーが表示。

Get value from agent failed: cannot connect to [[IP_address]:10050]: [4] Interrupted system call

環境

  • Zabbix server3.0.3
  • Zabbix agent3.0.3
  • CentOS7

対処法

1. SELinuxの確認

Zabbixエージェントの入ったホスト上でSELinuxが有効か無効か確認する

#現在の状態確認
getenforce
#有効だったら無効にする
sudo setenforce 0

2. ファイヤーウォールの確認

現在のファイヤーウォールの状態を確認し、Zabbixが登録されていない場合は追加する。

#ファイヤーウォールの状態確認
systemctl status firewalld
#ファイヤーウォール設定確認
firewall-cmd --list-all 
#Zabbixを追加する(サービスかポートか片方で大丈夫なはず)
#サービス追加
firewall-cmd --add-service=zabbix --zone=public --permanent
#ポート追加
firewall-cmd --add-port=10050/tcp --zone=public --permanent
#設定をリロードする
firewall-cmd --reload

リロードして"success"と表示されればOK!
"--permanent"を付けないとリロードしたら設定が無効になるので注意。

3. ZabbixのWebインターフェース画面を確認する

画面を更新すれば、赤くなっていたエラーメッセージが消えていると思います。

ElasticsearchにjsonをインポートしてGrafanaで可視化したい

何をやったのか

今回は、コマンドを打って取得した情報をjson形式に変換してElasticsearchにデータを流し込みます。Elasticsearchにデータを格納するときは、Metricbeatを通常使っているのですが、Metricbeatでは取得できない情報もElasticsearchに投入しGrafanaで可視化したかったので、そのためのシェルスクリプトを作りました。

コマンドで取得するデータはCephノードの情報です。
処理の流れとしては、以下の通りです。

  1. コマンドでCeph情報を取る
  2. タイムスタンプをデータに付ける
  3. データにインデックス情報を付与してElasticsearchに送る
  4. Elasticsearchにデータ登録されているか確認する
  5. Grafana上に登録する

Cephのコマンドは-fオプションで出力内容をjson等に変換できるので便利。-fの出力形式はjson, json-pretty, xml, xml-pretty, planeから選択することが出来ます。(※'pretty'がついてるのは見やすいように出力してくれる形式のこと。)
例えばこんな感じで。

ceph osd tree -f json

Cephのコマンドはどんなものがあるかは下記のサイトを参照すると良いです。どんなオプションがあるかは、ceph --helpでチェック。
www.lisa.jp

環境

  • Ceph12.2.5
  • Elasticsearch6.6.1
  • Grafana5.4

処理内容

実際に作成したスクリプトはこちら。

#!/bin/bash
#get ceph info
ceph_node_info=$(ceph node ls all -f json)
#timestamp for elasticsearch
date=`echo $(date "+%Y-%m-%dT%H:%M:%S.%3NZ")`
#date for index
date2=`echo $(date "+%Y-%m-%d-%H:%M")`

#setting of import data
index= '{"index":{"_index":"osd_'${date2}'","_type":"host_mapping"}}'
echo $index > result.json
echo '{"@timestamp":"'${date}'","ceph":['${ceph_node_info}']}' >> result.json

#send ceph info to elasticsearch
curl -s -H "Content_Type:application/json" -XPOST 'http://xxx.xx.xx.xx:9200/_bulk' --data-binary@result.json

Elasticsearchに送るjsonデータは、IndexとTypeを最初に指定する必要があります。Type_IDは省略可能です。
形式は以下の通りです。

#頭にインデックスを指定する
{ "index" : { "_index" : "[index_name], "_type" : "[type_name], "_id" : "[id]" } }
#続けてインポートするデータを書く
{"field_1":"value_1","field_2":"value_2"}

注意したいのは、1つのjsonデータにつきインデックス、タイプを指定する必要があるので下記のようなデータをインポートすることはできません。

#NG例
{ "index" : { "_index" : "[index_name], "_type" : "[type_name], "_id" : "[id]" } }
{"field_1":"value_1","field_2":"value_2"}
{"field_3":"value_3","field_4":"value_4"}

連続してデータをインポートするならば、下記のようにします。

#Ok例
{ "index" : { "_index" : "[index_name], "_type" : "[type_name], "_id" : "[id]" } }
{"field_1":"value_1","field_2":"value_2"}

{ "index" : { "_index" : "[index_name], "_type" : "[type_name], "_id" : "[id]" } }
{"field_3":"value_3","field_4":"value_4"}

つまづいたところ

タイムスタンプの位置

タイムスタンプの位置が悪くてGrafanaのデータソース登録の時にうまくいきませんでした。Grafanaのデータソース登録しようとすると、「No date field named @timestamp」というメッセージが。。。

何が悪かったかと言うと、cephフィールドの中にタイムスタンプを入れていたため認識されませんでした。なのでタイムスタンプをcephフィールドの外に出してデータソースの登録をすると成功!

#修正前
{"ceph":["@timestamp":"'${date}'",'${ceph_node_info}']}
#修正後
{"@timestamp":"'${date}'","ceph":['${ceph_node_info}']}

Grafanaのデータソースの登録方法は下記を見ると良いです。
私の大体下記の記事と同じように設定しています。
designetwork.daichi703n.com
注意点は、URLの後ろにポート指定すること(http://[elasticsearch_ip_address]:9200)、インデックス名やタイムフィールド名を間違えないことですかね?インデックス名は、私の場合YYYY.MM.DDの形式だと認識されなかったので、[index_name]-*に変えて登録すればデータソースが正常に追加されました。

括弧の位置とか数とか

jsonのフォーマットがよくわかってなくて[]で括るのか{}で括るのか悩みました。jsonのデータ構造が分かりにくかったら、jqコマンド等使うと見やすくなるので、間違いに気が付くと思います。
こんな感じで。

ceph osd tree -f json | jq .

大体エラーメッセージに何が悪いかかかれているので何回かトライ&エラーしてみるとよいです。