【Ubuntu】サービス立ち上げ

Ubuntu、サービス上げ下げsystemdやんか。 servicedに慣れたおっさんに辛い。(なんかビミョーにタイプしにくいんだ。。)

メモ

サービスあげる

systemctl start <サービス名>

サービスを止める

systemctl stop <サービス名>

サービス再起動

systemctl restart <サービス名>

サービスの状態

systemctl status <サービス名>

ログ(エラー詳細など) 下記「」には、systemctl statusで出てる実行ファイルを直接ぶっこむ。

journalctl <Matches>

ほかにも

詳しくは知らないけど、旧来のエコシステムが軒並みFuckだから、その一環できれいなsystemd作った経緯があるみたい。 類似の機能、あといい感じの機能があるんじゃないかな。

【Linux】UbuntuでCUIオンリーに切り替える

Ubuntu 16.04 LTS入れてCUI環境作ろうとしたら、何か妙に引っかかったので検索結果めも。

起動時にCUIにする

Linuxは起動時に読み込むrunlebelという設定値があって、 1~6の中のどれかを指定することでGUIとかCUIとかを切り替えたりする慣習あるんだけど、 今の?Ubuntuとかdebianは事情が異なって、「~.target」ファイルの指定を変えるらしい。

デスクトップ右クリック → 端末

sudo systemctl set-default multi-user.target

参考

キーボードレイアウトを変える

CUI環境、デフォだとなんか英語キーボードだった。 (デスクトップ環境は自動で設定されるみたい)

以下参照。

Ctrl + Alt + F1 とかで入れるまっくろ画面だと日本語が文字化けて読めないため、 以下実行してロケールを一時的に英語化。

sudo update-locale LANG=en_US.UTF-8 LANGUAGE="en_US.UTF-8" 
sudo source /etc/default/locale

(他のディストリビューションでも同じだけど、Ubuntuが直接乗っけてる直コンソールが  日本語対応してないから文字化ける。TeraTermなどで接続して同じバイトセット読み込むと  化けずに表示する。)

【Linux】cpとmvのファイル存在時の挙動。

cp

ファイル

宛先に同名のファイルが存在したとき

  • 上書きされる。環境によっては無言。
    • せめてもの回避法として、コピー時には以下のようにする流派がいるらしい。
# cp srcfile destfileに相当。間違って上書きしても、destfileに追記した部分を消せば復元できる。
cat srcfile >> destfile

宛先に同名のディレクトリが存在したとき

  • コピーしない。環境によっては無言

ディレクト

中に何かあるときは-rコマンドが必要。

cp -r srcdir destdir

いくつかのケースで分岐。

宛先に同名の「ファイル」が存在したとき

  • コピーしない

宛先が既に存在するディレクトリだった場合

# tree
.
|-- 1
|   `-- 1
`-- 2

3 directories, 0 files
# cp -r 1 2
# tree
.
|-- 1
|   `-- 1
`-- 2
    `-- 1
        `-- 1

5 directories, 0 files
#
  • 再帰コピーでコピー先とパスがかぶった場合、ファイルなら上書きする。
  • 再帰コピーでコピー先とパスがかぶった場合、ディレクトリならマージする。 ← !
  • ディレクトリがネストしていても対応。

mv

ファイル

宛先に同名のファイルが存在したとき

  • 上書きされる。環境によっては無言。
  • 超危険なため、設定ファイルの移動だけならば日常的にはcat srcfile >> destfileを推奨。

ディレクト

移動先のディレクト

宛先に同名の「ファイル」が存在したとき

  • 移動しない

宛先がまだ何も作られていないパスだった場合

  • 移動する

宛先が既に存在するディレクトリだった場合

  • 宛先のディレクトリ直下に名前そのままで移動する ← !?
# tree
.
|-- 1
|   `-- a
|       `-- b
|           `-- c
|               |-- d
|               `-- e
`-- 2

7 directories, 0 files
# mv 1 2
# tree
.
`-- 2
    `-- 1
        `-- a
            `-- b
                `-- c
                    |-- d
                    `-- e

7 directories, 0 files
#
  • 再帰コピーでコピー先とパスがかぶった場合、ファイルでもディレクトリでもエラーとなる。 ← !

ディレクトリの挙動、いまさらだけどこマ?ってなってる。 何か設定で依存するのかな。

【AngluarJS1】$httpリクエスト先が返してきたステータスコードによるIHttpProcessのsuccess、error

angularjsで$httpサービスでリクエストを問い合わせた際、HTTPステータスコードが200系以外だと 返却されるPromiseにてsuccessではなくerrorが呼び出される。

検証コード

status.php

<?php
http_response_code((int)$_GET['code']);

index.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta charset="utf-8">
<meta name="description" content="sample html">
<meta name="author" content="packpak">
<meta name="viewport" content="width=device-width, intial-scale=1">

<link rel="shortcut icon" href="">

<script src="angular.min.js"></script>
<script src="index.js"></script>
</head>
<body>
<div ng-app="app">
  <div ng-controller="mainCtrl as main">
    <button ng-click="main.send()">get</button>
  </div>
</div>
</body>
</html>

index.js

"use strict";

let app = angular.module('app', []);

class MainController {
  constructor($scope, $http) {
    this.host = '';
    this.$scope = $scope;
    this.$http = $http;
  }
  
  send() {
    for (let code of [200, 201, 204, 400, 401, 403, 404, 409, 500, 501]) {
      const url = "http://localhost/status.php?code=" + code;
      this.$http.get(url)
        .then(
          function(response) { console.log('status code:' + response.status) },
          function(response) { console.error('status code:' + response.status) }
      );
    }
  }
};

app.controller('mainCtrl', ['$scope', '$http', MainController]);

【Windowsバッチ・DOS】バッチファイルの環境変数スコープあれこれ

Windowsユーザーならみんなbatファイル好きだよね。 一度ははまるであろう環境変数のスコープについてあれこれをまとめる。

setコマンド

set 一時環境変数名=値

環境変数を一時設定する。 実行したコマンドプロンプト内でのみ有効。 (他のプロセスからは見えない。該当プロセスから立ち上がった子プロセスはスコープを引き継ぐ。コマンドプロンプト落とすと消える。)

ちなみに、ユーザー環境変数とかシステム環境変数といったものを恒久的に変えたければsetxコマンドを使うそうだ。

setlocalとendlocal

「バッチの中だけでスコープ切りたい!」ってときに使えるコマンド。

set X=outscope

setlocal

echo %X%
rem outscopeと表示される


set X=inscope

echo %X%
rem inscopeと表示される


endlocal

echo %X%
rem outscopeと表示される

pause

ブロック内で環境変数更新

皆がはまったであろう罠。

例えば、forで複数命令実行するときは( ... )で囲んでブロック化する。

for %%i in ( * ) do (
  set FILENAME=%%i
  echo ファイル名は「%FILENAME%」です
)

ところが、上のようにブロック内で環境変数を使った場合、コマンド実行時にfor~ブロック終わりの)までが一度評価されて、以下のように展開される。

for %%i in ( * ) do (
  set FILENAME=%%i
  echo ファイル名は「」です
)

むごい。

回避方法

回避方法を2つ紹介。

setlocal enabledelayedexpansion

setlocal enabledelayedexpansionと宣言すれば、遅延環境変数というものが使える。

setlocal enabledelayedexpansion
for %%i in ( * ) do (
  set FILENAME=%%i
  echo ファイル名は「!FILENAME!」です
)

サブルーチン化

callで別処理に呼ぶと回避できる。

for %%i in ( * ) do (
  call :PRINTNAME %%i
)

goto :END

:PRINTNAME
echo ファイル名は「%1」です
exit /b

:END

pause

【Windowsバッチ・DOS】標準出力・リダイレクト回りまとめ

CUIツールを作ったので色々メモ。

標準出力をファイルにリダイレクト

echo text > stdlog.txt

標準エラーをファイルにリダイレクト

mkdir c:\ 2> errorlog.txt

標準出力と標準エラーをまとめてファイルにリダイレクト

mkdir c:\ > log.txt 2>&1

コンソールにも出力してリダイレクトにも書く

結論から言うと、DOSの標準環境だけじゃ無理。 全部出力し終えてから一気に表示するだけならtypeを使えばよい。

環境は限られるが、 Linuxにteeというコマンドがあり、Windows実装にした「safetee」というツールが有名。

safetee www.vector.co.jp

Linux teeコマンド

【 tee 】 標準入力を標準出力とファイルに出力する | 日経クロステック(xTECH)

2022/08/23 追記:久しぶりにこの周りをいじっていたところ、素晴らしいVBSを公開されているかたがいた。

qiita.com

このスクリプトをShiftJISのtee.vbsとして保存し、「cscript tee.vbs /a sample.log」などと打つと動作する。

【Java】Tar、GZを読み込む

Linux標準の圧縮形式、tar.gz。業務で、Javaの小物を作ることになったのでメモ。

tar.gzの仕組み

2段階に圧縮している。

ファイル
  |
(複数ファイルをTARで1つのバイナリに連結)
  ↓
TARファイル
  |
(1ファイルをGZip圧縮)
  ↓
TAR.GZファイル

Javaのライブラリ

今回は、Java標準のGZIPInputStreamApache Commons CompressのTarArchiveInputStreamを使った。

File outDir = new File("/outdir");
File gzipFile = new File("sample.tar.gz");

try (FileInputStream fis = new FileInputStream(gzipFile)) {
    try (GZIPInputStream gis = new GZIPInputStream(fis)) {
        try (TarArchiveInputStream tis = new TarArchiveInputStream(gis)) {
            for (AchiveEntry entry = tis.getNextEntry(); entry != null; entry = tis.getNextEntry()) {
                if (entry.isDirectory()) {
                    File newDir = new File(outDir, entry.getName());
                    if (!newDir.mkdirs()) {
                        throw new IOException("directory " + newDir.getAbsolutePath() + " cannot create.');
                    }
                } else {
                    File newfile = new File(outDir, entry.getName());
                    File parentDir = newfile.getParent();
                    if (!parentDir.mkdirs()) {
                        throw new IOException("directory " + parentDir.getAbsolutePath() + " cannot create.');
                    }
                    try (FileOutputStream fos = new FileOutputStream(newfile)) {
                        IOUtils.copy(tis, fos);  // Apache common-io
                    }
                }
            }
        }
    }
}

なんだこのネスト。やってることは単純なんだけど。

TarAchiveInputStreamのAPIがやや癖があって、getNextEntryすると、TarArhiveInputStreamのファイルポインタが進む。

また、GZIPInputStreamには作業バッファ長が与えられる。だいたい、デフォルトの8196で十分だが、CPUリソースが余りに余るようであれば増やしてもよいかもしれない。