20210901のLinuxに関する記事は4件です。

Nginxが再起動できなかった場合の対処法

Nginxのリスタートでエラー Nginxを再起動した際にNginxがエラーを出力させた、なぜだ?? $ sudo systemctl restart nginx # エラーの発生 # job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details. とりあえずエラーメッセージを実行する $ systemctl status nginx.service $ journalctl -xe うーん、、、 なんとなくプロセスが残ってるのかなと思った 解決方法 とりあえずNginxのプロセスを確認してみよう。 $ sudo lsof -i | grep nginx nginx 15930 ~ nginx 15930 ~ nginx 15930 ~ nginx 15941 ~ nginx 15941 ~ nginx 15941 ~ nginx 15942 ~ nginx 15942 ~ nginx 15942 ~ 残ってた笑 それじゃkillコマンドで強制的に終了させよう(-9で強制) $ sudo kill -9 15930 $ sudo kill -9 15941 $ sudo kill -9 15942 Nginxの プロセスを再度確認 $ sudo lsof -i | grep nginx 消えた、これで実行だ!!!!!!!! $ sudo systemctl restart nginx 動いた!!!!!! 結論 焦らずプロセスの確認をしましょう笑
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

対話型コマンドを実行するShellScriptのテスト用ツールを作った話

オンプレミスのインフラエンジニアをやっていると、運用スクリプトを作ることがあります。 監視やバックアップなどの運用を自動化するものです。 ぜひ自動化して運用で楽をしたいものですが、品質担保には思った以上の工数がかかってしまいます。 そこで私は単体テストを実施したい!と思ったのですが、JUnitのようにツールを入れれば行けるというわけでもなさそうでした。 対話型コマンドが絡むシェルのテストのやりづらさ 運用スクリプトの中には、実行したら必ず0を返すような何も工夫しなくても書けるスタブでコマンドを置き換えることでテスト出来る場合もありますが、DBのバックアップなどでスクリプト内でミドルウェア特有のコマンドをたたいているような場合、スタブ化するために少し工夫がいります。 ShellTestStarterの紹介 というわけで作りました。 無駄にREADMEもきれいにしてみました。 releaseからzipをダウンロードするもよし、git cloneするもよし、コードを除いて必要なところだけパクるもよし。好きに使ってください。 READMEにも書きましたが、Linuxのみで動作確認しています。確認環境はCentOS 7 ですので、RHEL系だとそのまま動くと思います。(Ubuntuでも多分動く) Quick Start - サンプルの動かし方 Dockerでの動作が楽なので、 docker-compose run c_dev_env /bin/bash としてコンテナを起動し、シェルに入ってからsampleに移動してsetup.shを実行します。 [root@<containerid> workdir]# cd sample/ [root@<containerid> sample]# ./setup.sh INFO: prepare stub script gcc -o template_communicate_stub template_communicate_stub.c done prepare! makeでのコンパイル、スタブスクリプトの作成が行われるので、試しにテストスクリプトを実行してみましょう。 test_sample_backup_script.shを実行します。 [root@<containerid> sample]# ./test_sample_backup_script.sh begin sample backup script test OK: test case 1 OK: test case 2 OK: test case 3 OK: test case 4 OK: test case 5 OK: test case 6 OK: test case 7 OK: test case 8 OK: test case 9 complete database backup test 全てOKとなっているので、全件テスト通過です。 完了したらsetup.sh cleanを実行することで、生成したファイルたちをクリーンアップできます。 [root@<containerid> sample]# ./setup.sh clean INFO: clean all scripts generated by this script INFO: remove sqlplus INFO: remove sqlplus.dat INFO: remove rman INFO: remove rman.dat INFO: remove db_check.sh INFO: remove db_check.dat INFO: all done! テンプレートスクリプトの解説 テンプレートはsrcの中にtemplate_というプレフィックスで格納されています。 src │ Makefile │ template_communicate_stub.c │ template_communicate_stub.dat │ template_simple_stub.dat │ template_simple_stub.sh template_simple_stub.sh シンプルなスタブシェルです。template_simple_stub.datに記載されている値を読み取って、そのまま返却します。 引数を与えて実行すると、それをそのままログに吐き出します。 template_simple_stub.sh #!/bin/bash script_name=$(basename $0) script_logname=test_$script_name.log echo "run $script_name" >>$script_logname if [ $# -eq 0 ]; then echo "no argument" >>$script_logname else for arg in "$*"; do echo "argument: $arg" >>$script_logname done fi exit $(cat ${script_name%.*}.dat) template_communicate_stub.c 対話式コマンド用のスタブです。同名の.datファイルを読み込み最終的な返却値とします。 引数を与えた時はバッファとして読み込み、引数なしで実行した場合は対話モードで実行できます。 いずれにせよ、読み込んだ文字列はただそのまま吐き出すだけです。 template_communicate_stub.c #include <stdio.h> #include <string.h> #include <unistd.h> // Function to get the path of the execution command // Only available on Linux char *getfilepath() { static char buf[1024] = {"\0"}; readlink("/proc/self/exe", buf, sizeof(buf) - 1); return buf; } int main(int argc, char *argv[]) { // If the beginning of argv[0] (execution command) is ./, remove it. char cmd_name[64]; sscanf(argv[0], "%s", &cmd_name); char t[64]; if (cmd_name[0] == '.' && cmd_name[1] == '/') { // included strncpy(t, cmd_name + 2, strlen(cmd_name) - 2); t[strlen(cmd_name) - 2] = '\0'; } else { // not included strncpy(t, cmd_name, strlen(cmd_name)); t[strlen(cmd_name)] = '\0'; } // Reading here documents int i; printf("run command: %s", t); for (i = 1; i < argc; i++) { printf(" %s", argv[i]); } char buffer[256] = ""; printf("\n---heredoc recieved from here---\n"); // Loop part that accepts input from here documents and terminals while (1) { if (scanf("%255[^\n]%*[^\n]", buffer) == EOF) { break; } // Exit the loop when exit is entered if (strstr(buffer, "exit") != NULL) { break; } // Abnormal termination when a specific character is entered if (strstr(buffer, "special keyword") != NULL) { return 1; } scanf("%*c"); printf("> %s\n", buffer); } printf("---heredoc end---\n"); // File reading char fname[64]; sscanf(getfilepath(), "%s", &fname); strcat(fname, ".dat"); FILE *fp; fp = fopen(fname, "r"); // Get the value from the file and return it as it is int ret; while (fscanf(fp, "%d", &ret) != EOF) { } fclose(fp); return ret; } サンプルテストスクリプトの説明 サンプルとして、以下のようなスクリプトを用意しています。 src/sample/ sample_backup_script.sh setup.sh test_sample_backup_script.sh sample_backup_script.sh バックアップスクリプトのサンプルです。このサンプルスクリプトのテストを行う例でsetup.shとtest_sample_backup_script.shを作っています。 このスクリプトはOracleでのバックアップを模したものになっており、sqlplus、rmanを使ってバックアップ処理を行い、db_check.shという架空のチェックスクリプトを実行する処理となっています。 サンプルですので、こちらを実行しても正しくバックアップが取れないでし、エラーハンドリングもかなりお粗末で実際はsqlplusやrmanが出力するエラーを検知するように作った方が良いと思います。あくまで参考としてください。 sample_backup_script.sh #!/bin/bash # Oracle backup script example logname="sample_backup_script.log" echo "INFO: sample backup script" >>$logname # Check the startup status of the instance sqlplus target / 2>&1 >/dev/null <<EOF select instance_name,status from v\$instance; EOF ret=$? if [ ! $ret -eq 0 ]; then echo "ERROR: instance state incorrect" >>$logname exit 100 fi # Backup process rman target / 2>&1 >/dev/null <<EOF backup database; EOF ret=$? if [ ! $ret -eq 0 ]; then echo "ERROR: backup failure" >>$logname exit 101 fi # Check processing ./db_check.sh full ret=$? if [ ! $ret -eq 0 ]; then echo "ERROR: check failed" >>$logname exit 102 fi echo "INFO: complete database backup" >>$logname setup.sh このsample_backup_script.shをテスト実行するために、必要なスタブを準備するスクリプトです。 setup.shは汎用的に作っていますので、変数宣言の部分だけ変えて流用いただいてもいいと思います。 setup.sh #!/bin/bash # variable declaration array_communicate_stub=(sqlplus rman) array_simple_stub=(db_check) tmp_com_stub=template_communicate_stub tmp_simple_stub=template_simple_stub # mode to delete the script created by setup.sh # execute only when clean is given as an argument if [ "$1" == "clean" ]; then echo "INFO: clean all scripts generated by this script" # remove stubs based on template_communicate_stub for item in ${array_communicate_stub[@]}; do if [ -e ./${item} ]; then rm ./${item} echo "INFO: remove ${item}" fi if [ -e ./${item}.dat ]; then rm ./${item}.dat echo "INFO: remove ${item}.dat" fi done # creating a stub based on template_simple_stub for item in ${array_simple_stub[@]}; do if [ -e ./${item}.sh ]; then rm ./${item}.sh echo "INFO: remove ${item}.sh" fi if [ -e ./${item}.dat ]; then rm ./${item}.dat echo "INFO: remove ${item}.dat" fi done cd .. rm ./${tmp_com_stub} echo "INFO: all done!" exit 0 fi # If there are no arguments, do the following # Describe the preparation process when executing the test echo "INFO: prepare stub script" if [ ! -e ../${tmp_com_stub} ]; then current_dir=$(pwd) cd .. make cd $current_dir fi # Creating a stub based on template_communicate_stub for item in ${array_communicate_stub[@]}; do cp -pr ../${tmp_com_stub} ./${item} cp -pr ../${tmp_com_stub}.dat ./${item}.dat done # Creating a stub based on template_simple_stub for item in ${array_simple_stub[@]}; do cp -pr ../${tmp_simple_stub}.sh ./${item}.sh cp -pr ../${tmp_simple_stub}.dat ./${item}.dat done echo "done prepare!" 変数は以下のようになっています array_communicate_stub=(sqlplus rman) # template_communicate_stubをもとに作成するスタブのリスト array_simple_stub=(db_check) # template_simple_stub.shをもとに作成するスタブのリスト tmp_com_stub=template_communicate_stub # 対話式コマンドのスタブスクリプトテンプレート名 tmp_simple_stub=template_simple_stub # 単純なスタブスクリプトテンプレート名 test_sample_backup_script.sh sample_backup_script.shのいわゆるテストドライバです。スタブコマンドの返却値を制御する各.datファイルを書き換えながら、テストを実行⇒観点ごとに合否を判断しています。 その他注意点としてはexport PATH=./:$PATHとして、スタブコマンドにパスを通しています。もともとのパスよりも前にスタブコマンドにパスを通しておくことで、実際のコマンドではなくスタブコマンドの方を実行するようになります。 test_sample_backup_script.sh #!/bin/bash # this is sample test script logname="sample_backup_script.log" # function that returns all stubs with 0 function allStateClear() { echo 0 >./sqlplus.dat echo 0 >./db_check.dat echo 0 >./rman.dat } echo "begin sample backup script test" export PATH=./:$PATH # test case 1 : When completed, the return value must be 0 allStateClear ./sample_backup_script.sh ret=$? if [ $ret -eq 0 ]; then echo "OK: test case 1" else echo "NG: test case 1 : [ret : ${ret}]" fi # test case 2 : INFO: complete database backup is output to the log allStateClear ./sample_backup_script.sh ret=$(tail -n 1 $logname | grep "INFO: complete database backup" | wc -l) if [ $ret -eq 1 ]; then echo "OK: test case 2" else echo "NG: test case 2" fi # test case 3 : The argument full is passed to db_check allStateClear ./sample_backup_script.sh ret=$(tail -n 2 ./test_db_check.sh.log | grep "argument: full" | wc -l) if [ $ret -eq 1 ]; then echo "OK: test case 3" else echo "NG: test case 3" fi # test case 4 : If the confirmation of the instance startup status fails, # the return value must be 100. allStateClear echo 1 >./sqlplus.dat ./sample_backup_script.sh ret=$? if [ $ret -eq 100 ]; then echo "OK: test case 4" else echo "NG: test case 4 : [ret : ${ret}]" fi # test case 5 : If the confirmation of the instance startup status fails, # an error has been output to the log. allStateClear echo 1 >./sqlplus.dat ./sample_backup_script.sh ret=$(tail -n 1 $logname | grep "ERROR: instance state incorrect" | wc -l) if [ $ret -eq 1 ]; then echo "OK: test case 5" else echo "NG: test case 5" fi # test case 6 : If the backup process fails, the return value must be 200 allStateClear echo 1 >./rman.dat ./sample_backup_script.sh ret=$? if [ $ret -eq 101 ]; then echo "OK: test case 6" else echo "NG: test case 6 : [ret : ${ret}]" fi # test case 7 : If the backup process fails, an error has been output to the log. allStateClear echo 1 >./rman.dat ./sample_backup_script.sh ret=$(tail -n 1 $logname | grep "ERROR: backup failure" | wc -l) if [ $ret -eq 1 ]; then echo "OK: test case 7" else echo "NG: test case 7" fi # test case 8 : If the check process fails, the return value must be 300 allStateClear echo 1 >./db_check.dat ./sample_backup_script.sh ret=$? if [ $ret -eq 102 ]; then echo "OK: test case 8" else echo "NG: test case 8 : [ret : ${ret}]" fi # test case 9 : If the check process fails, an error has been output to the log. allStateClear echo 1 >./db_check.dat ./sample_backup_script.sh ret=$(tail -n 1 $logname | grep "ERROR: check failed" | wc -l) if [ $ret -eq 1 ]; then echo "OK: test case 9" else echo "NG: test case 9" fi echo "complete database backup test" Shell Scriptのテストの書き方 Shell Scriptで作られた運用ツールって、監視だったりバックアップだったり、システム的にはかなり重要な役割を担っていたりするのに、システムテストはやるにしてもスクリプト単体でのテストってあまり行われていない気がします。 理由の一つはスクリプト自体が短いものが多く、あまり単体でテストをやる意味がないと思われているように感じます。ですが、自動で単体テストをやるように仕組みを作っておくことで、品質の担保ももちろんですが仕様変更に強くなるというメリットがあります。 ここではShellTestStarterのサンプルを例にどのようにテストを実現しているか解説します。 単純な正常系 allStateClearという各.datファイルの値を0に上書きする処理で返却値をリセットし、sample_backup_script.shを実行しています。返却値が0であるかどうかを見て、試験の合否を判別しています。 # test case 1 : When completed, the return value must be 0 allStateClear ./sample_backup_script.sh ret=$? if [ $ret -eq 0 ]; then echo "OK: test case 1" else echo "NG: test case 1 : [ret : ${ret}]" fi サンプルではケースを分けていますが、正常終了したというログを出力するような場合は、合否判定にそこまで含めても良いと思います。 ログを後半1行だけ読み込み、出力されるはずのメッセージがあるかどうか確認して、あれば合格としています。 # test case 2 : INFO: complete database backup is output to the log allStateClear ./sample_backup_script.sh ret=$(tail -n 1 $logname | grep "INFO: complete database backup" | wc -l) if [ $ret -eq 1 ]; then echo "OK: test case 2" else echo "NG: test case 2" fi コマンドに正しい引数が渡されているかどうかを確認 スタブコマンドはtest_<コピー後のスクリプト名>.logというログを直下に吐き出す仕様となっています。 ですので、そのログを見ることで、コマンドに正しい引数が渡されているかを確認することが出来ます。 allStateClear ./sample_backup_script.sh ret=$(tail -n 2 ./test_db_check.sh.log | grep "argument: full" | wc -l) if [ $ret -eq 1 ]; then echo "OK: test case 3" else echo "NG: test case 3" fi オプション等で処理を変えて、子スクリプトに別々の引数を渡すようなスクリプトの場合に役立つと思います。 異常系 異常系に関しても判定方法は同じですが、エラーを意図的に発生させています。 allStateClearを実行してクリアした後、echo 1 >./sqlplus.datのように、直接返却値を書き込むことで、同名のコマンドが書き込んだ返却値を返すようになります。 この例ではsqlplusが0以外を返した場合は、ログにERRORを出力し、100を返却するようにしていますので、想定している動作となるかを確認します。 # test case 4 : If the confirmation of the instance startup status fails, # the return value must be 100. allStateClear echo 1 >./sqlplus.dat ./sample_backup_script.sh ret=$? if [ $ret -eq 100 ]; then echo "OK: test case 4" else echo "NG: test case 4 : [ret : ${ret}]" fi まとめ 今回はShellScriptのテスト自動化ツールを公開した説明記事でした。 プルリクもお待ちしておりますのでよろしくお願いします
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ファイルのアクセス権を変更するchmodコマンドについて理解する!

アクセス権 chmod(チェンジモード) ファイルのアクセス権を変更します。 ls -lでhoge.jsのファイルの情報を見てみます。 表示されている左側のrw-r--r--の部分がアクセス権を表しています。最初の「 - 」を除き、最初の「 - 」以降の-を含めて9桁ありますが、3桁区切りずつで見ていきます。(一番最初の「 - 」の意味ですが、ファイルの種類を表しています。「 - 」は普通のファイル「 d 」ならディレクトリを表します) -rw-r--r-- 1 example staff 0 8 30 14:27 hoge.js 左から3桁ずつそれぞれ、所有するユーザー( rw- )、所有するグループ( r-- )、その他のユーザー(r--)に対する権限を表しています。アクセス権には、読み取り可能( r )、書き込み可能( w )、実行可能( x )の3種類があります。「 - 」はその部分のアクセス権がないことを意味しています。 権限を変更する場合、オプションの記述方法には数字を用いる方法と文字を用いる方法があります(ここでは数字の方を紹介します) 数字で表す場合、読み取り権( r )が4、書き込み権( w )が2、実行権( x )が1となります。 読み取り権 書き込み権 実行権 r w x 4 2 1 ・読み取り権 = そのファイルに対して読み取ることはできますが変更は加えられません。 ・書き込み権 = そのファイルに対して変更を加えたり削除することができます。 ・実行権 = そのファイルを実行することができます。 例えばls -lとした時に下記-rw-r--r--のような表示ですと、最初の「 - 」は除いて3桁づつに区切って考えるので rw- = 4+2+0 = 6, r-- = 4+0+0 = 4, r-- = 4+0+0 = 4 合わせて644と表すことができます。 -rw-r--r-- 1 example staff 0 8 30 14:27 hoge.js ↑ ↑ ↑ 6 4 4 また下記のように全てrwxとなっていますと、4+2+1で7となり、777ということになります。つまり所有するユーザー、所有するグループ、その他のユーザーそれぞれに全ての権限が付与されている状態となっています。 -rwxrwxrwx 1 example staff 0 8 30 14:27 hoge.js ↑ ↑ ↑ 7 7 7 上記のような全てのユーザーが全ての権限を持つ、777が付与されているファイルhoge.jsがあるとします。これを所有するユーザーのみ読み書き可能な権限を持つように変更したい場合は chmod 600 hoge.js と実行しls -l hoge.jsで確認してみると -rw------- 1 example staff 0 8 30 14:27 hoge.js 権限が変更されていることが確認できます。rw----r--なら604、rwxrw-rw-なら766といった具合です。 このように、「rwx」にそれぞれを数字に直した値をオプションに指定してアクセス権を変更します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Chromebook で blender

Chromebook で blenderを動かしてみる Chromebook で Linux開発環境が使用できるようになりました ということで、3Dモデリングなどで有名なblenderは動くのか???試してみました 1. Linux環境のインストール 設定からLinux開発環境をオンにするを実行 セットアップ画面。ユーザ名(半角英数)などを入力して「インストール」をクリック インストール中 インストール完了 Linuxコマンドラインが表示される メニューを確認 2.Linuxコマンド実行 apt コマンドで更新(apt update と apt upgrade) $ sudo apt update $ sudo apt upgrade 更新作業が行われる 更新完了 3. blender インストール $ sudo apt install blender インストール終了 メニューを確認 4.メニューから起動 メニューからblenderを起動する 動きました! 普通に動きます。Chromebookでblender使えそうです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む