Shell Script の set -e が招く事故を回避:pipefail・サブシェル・条件分岐の落とし穴
シェルスクリプトで「エラーが発生したら即座にスクリプトを停止させたい」と考えたとき、多くの開発者が set -e を利用します。この設定は一見便利に思えますが、実は予期しない動作を招く落とし穴がいくつも存在するのです。
特にパイプライン処理、サブシェル、条件分岐といった場面では、set -e が期待通りに機能せず、エラーを見逃してしまうケースがあります。本記事では、set -e の基本から、pipefail オプション、サブシェルや条件分岐における注意点まで、実践的な例とともに詳しく解説していきますね。
この記事を読むことで、シェルスクリプトのエラー処理を確実に行い、本番環境での予期せぬ事故を未然に防げるようになるでしょう。
背景
シェルスクリプトにおけるエラー処理の重要性
シェルスクリプトは、サーバーのセットアップ、デプロイ作業、バッチ処理など、インフラ運用の現場で広く使われています。これらの処理では、一つのコマンドが失敗しても次のコマンドが実行され続けてしまうと、データの不整合や予期しないシステム状態を招く危険性があります。
例えば、データベースのバックアップスクリプトで以下のような処理を考えてみましょう。
bash#!/bin/bash
# データベースバックアップの例(問題あり)
# バックアップディレクトリを作成
mkdir /backup/db
# データベースをダンプ
mysqldump -u root -p mydb > /backup/db/mydb.sql
# 古いバックアップを削除
rm -rf /backup/old/*
このスクリプトでは、mkdir コマンドが失敗(例:ディスク容量不足)しても、次の mysqldump が実行され、意図しない場所にファイルが出力される可能性があります。
デフォルトのシェル動作
Bash などのシェルは、デフォルトでコマンドが失敗してもスクリプトを継続実行します。この動作は柔軟性を提供する一方で、エラーハンドリングを意識しないと重大な問題につながります。
以下の図で、デフォルトのシェル動作を確認しましょう。
mermaidflowchart TD
start["スクリプト開始"] --> cmd1["コマンド1 実行"]
cmd1 --> check1{成功?}
check1 -->|成功| cmd2["コマンド2 実行"]
check1 -->|失敗| cmd2
cmd2 --> check2{成功?}
check2 -->|成功| cmd3["コマンド3 実行"]
check2 -->|失敗| cmd3
cmd3 --> finish["スクリプト終了"]
図の要点:
- コマンドが失敗しても次のコマンドが実行される
- エラーを明示的に処理しない限り、スクリプトは最後まで実行される
- 途中のエラーに気付かず、データの不整合が発生するリスクがある
set -e の登場
この問題を解決するために set -e(または set -o errexit)オプションが用意されています。このオプションを有効にすると、コマンドが 0 以外の終了ステータスを返した時点でスクリプトが即座に終了します。
bash#!/bin/bash
set -e # エラー時に即座に終了
mkdir /backup/db
mysqldump -u root -p mydb > /backup/db/mydb.sql
rm -rf /backup/old/*
この設定により、mkdir が失敗すればその時点でスクリプトが停止し、後続の危険な処理を防げるわけです。
課題
set -e の落とし穴:期待通りに動作しないケース
set -e は便利に見えますが、実際にはいくつかの状況で機能しないという問題があります。これを理解せずに使うと、「エラー処理をしているつもり」が「実際にはエラーを見逃している」状態になってしまいます。
以下の図で、set -e が無効になる主なケースを示します。
mermaidflowchart TB
sete["set -e 設定"] --> case1["パイプライン処理"]
sete --> case2["サブシェル実行"]
sete --> case3["条件分岐"]
sete --> case4["論理演算子"]
case1 --> issue1["パイプの途中のエラーを<br/>検出できない"]
case2 --> issue2["サブシェル内のエラーが<br/>親に伝わらない"]
case3 --> issue3["if/while文内では<br/>set -e が無効"]
case4 --> issue4["&& や || と組み合わせると<br/>無効化される"]
図で理解できる要点:
set -eには 4 つの主要な落とし穴がある- それぞれの状況で異なる回避策が必要
- これらを理解しないと、エラーハンドリングに穴が生まれる
課題 1:パイプライン処理でのエラー検出漏れ
パイプライン(|)を使ったコマンド連結では、最後のコマンドの終了ステータスのみが評価されます。途中のコマンドが失敗しても、set -e は発動しません。
bash#!/bin/bash
set -e
# 以下のコマンドで grep が何もマッチせず失敗しても
# スクリプトは停止しない
cat non_existent_file.txt | grep "pattern" | wc -l
echo "このメッセージは表示される"
この例では、cat コマンドがファイルを見つけられず失敗(終了ステータス: 1)しますが、wc -l は正常終了(終了ステータス: 0)するため、スクリプトは継続されます。
課題 2:サブシェルでのエラー伝播の問題
サブシェル($(...) や (...) で囲まれた部分)内で発生したエラーは、親シェルに伝播しないケースがあります。
bash#!/bin/bash
set -e
# サブシェル内でエラーが発生
result=$(false; echo "executed")
echo "result: $result" # この行も実行される
echo "スクリプトは継続される"
上記の例では、サブシェル内の false コマンドは失敗しますが、サブシェル全体の終了ステータスは最後のコマンド(echo)のものになるため、スクリプトは停止しません。
課題 3:条件分岐内での set -e の無効化
if 文、while 文、&& や || などの条件判定では、set -e が一時的に無効化されます。これは、条件判定そのものがコマンドの成功/失敗を評価する仕組みだからです。
bash#!/bin/bash
set -e
# if文の条件部ではset -eが無効
if false; then
echo "実行されない"
fi
echo "スクリプトは継続される(期待と異なる)"
この動作は POSIX 仕様で定義されていますが、多くの開発者が予期しない挙動と感じる部分でしょう。
課題 4:論理演算子との組み合わせ
&& や || と組み合わせた場合も、set -e は機能しません。
bash#!/bin/bash
set -e
# &&の前のコマンドが失敗しても継続
false && echo "実行されない"
echo "スクリプトは継続される"
以下の表で、set -e が有効/無効になる状況をまとめます。
| # | 状況 | set -e の動作 | 備考 |
|---|---|---|---|
| 1 | 通常のコマンド実行 | ★ 有効 | エラー時に即座に終了 |
| 2 | パイプライン cmd1 | cmd2 | ☆ 無効(最後のみ) | pipefail が必要 |
| 3 | サブシェル $(cmd) | ☆ 条件付き | サブシェル全体の終了ステータスに依存 |
| 4 | if 文の条件部 | ☆ 無効 | 条件評価のため |
| 5 | while 文の条件部 | ☆ 無効 | 条件評価のため |
| 6 | && や || との組み合わせ | ☆ 無効 | 論理演算のため |
解決策
解決策 1:pipefail オプションの活用
パイプライン処理でのエラー検出漏れを防ぐには、set -o pipefail を使用します。
pipefail の基本設定
pipefail オプションを有効にすると、パイプライン内のいずれかのコマンドが失敗した場合、パイプライン全体が失敗として扱われるようになります。
bash#!/bin/bash
set -e
set -o pipefail # パイプライン処理のエラー検出を有効化
これにより、以下のような処理でも確実にエラーを検出できます。
bash#!/bin/bash
set -e
set -o pipefail
# cat が失敗すると、パイプライン全体が失敗しスクリプトが停止
cat non_existent_file.txt | grep "pattern" | wc -l
# この行は実行されない
echo "到達しない"
pipefail の詳細な動作
pipefail を設定すると、パイプライン内の最も右にある失敗したコマンドの終了ステータスが返されます。
bash#!/bin/bash
set -e
set -o pipefail
# 以下は失敗する(cat の終了ステータス: 1)
# grepが成功してもcatの失敗が検出される
cat missing.txt | grep "test"
複数のコマンドが失敗した場合の動作も確認しましょう。
bash#!/bin/bash
set -o pipefail
# 複数のコマンドが失敗した場合
false | true | false
echo "終了ステータス: $?" # 1が表示される(最後のfalseの値)
解決策 2:サブシェルのエラー処理
サブシェルでのエラーを確実に検出するには、以下の方法があります。
方法 1:サブシェルの終了ステータスを明示的にチェック
コマンド置換 $(...) を使う場合、サブシェル内で確実にエラーを伝播させる必要があります。
bash#!/bin/bash
set -e
# サブシェル内で set -e を有効にし、
# 最後にエラーチェックを明示
result=$(
set -e
false
echo "この行は実行されない"
)
# または、サブシェルの後に明示的にチェック
result=$(some_command) || exit 1
方法 2:サブシェル内でも set -e を設定
サブシェル内で独立して set -e を設定することで、エラーハンドリングを強化できます。
bash#!/bin/bash
set -e
# サブシェル内でもset -eを明示
output=$(
set -e
set -o pipefail
curl -f https://api.example.com/data
jq '.items[] | .name'
)
echo "取得データ: $output"
方法 3:中括弧でのグルーピング
サブシェルではなく、中括弧 { ... } でコマンドをグループ化すると、親シェルと同じコンテキストで実行されます。
bash#!/bin/bash
set -e
# サブシェルではなくコマンドグループを使用
{
echo "処理開始"
false # ここでスクリプトが停止する
echo "到達しない"
}
解決策 3:条件分岐での安全なエラー処理
条件分岐内で set -e が無効になる問題には、以下のアプローチが有効です。
方法 1:条件の外で終了ステータスを保存
bash#!/bin/bash
set -e
# コマンドを実行して終了ステータスを保存
some_command
status=$?
# 保存した終了ステータスを評価
if [ $status -ne 0 ]; then
echo "エラー: コマンドが失敗しました(終了コード: $status)"
exit 1
fi
この方法により、if 文の中でコマンドを直接実行せず、事前に実行結果を評価できます。
方法 2:if 文内で明示的にエラーチェック
if 文内でコマンドを実行する場合は、エラー時に明示的に exit を呼び出します。
bash#!/bin/bash
set -e
if some_condition; then
# if文内では set -e が効かないため、明示的にチェック
critical_command || {
echo "Error: critical_command が失敗しました" >&2
exit 1
}
fi
方法 3:command の代わりに ! command を使う
条件判定で成功を期待する場合は、二重否定を使うテクニックもあります。
bash#!/bin/bash
set -e
# 失敗を期待する場合(例: ファイルが存在しないことを確認)
if ! [ -f "/path/to/file" ]; then
echo "ファイルが存在しません(正常)"
fi
ただし、このアプローチは可読性を下げる可能性があるため、チーム内での規約を決めておくとよいでしょう。
解決策 4:論理演算子との安全な組み合わせ
&& や || を使う場合は、以下のように記述します。
エラー時の即座の停止
bash#!/bin/bash
set -e
# &&を使う場合は、失敗時にexitを明示
command1 && command2 || exit 1
より明示的な記述
bash#!/bin/bash
set -e
# 可読性を重視した記述
if command1; then
command2
else
echo "Error: command1 が失敗しました" >&2
exit 1
fi
ベストプラクティス:推奨される設定セット
以下は、堅牢なシェルスクリプトを書くための推奨設定です。
bash#!/bin/bash
# エラー時に即座に終了
set -e
# パイプライン内のエラーを検出
set -o pipefail
# 未定義変数の使用をエラーとする
set -u
# デバッグ時はコマンドをトレース表示
# set -x
これらの設定により、以下のようなエラーを防げます。
| # | オプション | 防げるエラー | 例 |
|---|---|---|---|
| 1 | set -e | コマンド失敗の見逃し | mkdir 失敗後の cd 実行 |
| 2 | set -o pipefail | パイプライン内のエラー見逃し | cat file | grep pattern で cat 失敗 |
| 3 | set -u | 未定義変数の参照 | $TYPO_VARIABLE のような変数名ミス |
| 4 | set -x | デバッグ情報の不足 | 処理の流れが追跡できない |
具体例
実例 1:データベースバックアップスクリプト
以下は、これまでの解決策を組み合わせた実践的なバックアップスクリプトです。
スクリプト全体の設定
bash#!/bin/bash
# 堅牢なエラー処理を設定
set -e # エラー時に終了
set -o pipefail # パイプラインのエラー検出
set -u # 未定義変数の使用を禁止
変数定義と初期設定
bash# バックアップ設定
BACKUP_DIR="/backup/mysql"
DB_NAME="production_db"
DB_USER="backup_user"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${TIMESTAMP}.sql.gz"
ディレクトリ作成(エラーチェック付き)
bash# バックアップディレクトリの作成
# -p オプションで既存ディレクトリでもエラーにならない
mkdir -p "${BACKUP_DIR}" || {
echo "Error: バックアップディレクトリを作成できません" >&2
exit 1
}
データベースダンプ(パイプライン処理)
bash# データベースをダンプして圧縮
# pipefailにより、mysqldumpまたはgzipの失敗を検出
mysqldump -u "${DB_USER}" -p"${DB_PASS}" "${DB_NAME}" \
| gzip -9 \
> "${BACKUP_FILE}"
上記のパイプライン処理では、mysqldump が失敗した場合も gzip が失敗した場合も、set -o pipefail により確実に検出されます。
バックアップの検証
bash# バックアップファイルが作成されたか確認
if [ ! -f "${BACKUP_FILE}" ]; then
echo "Error: バックアップファイルが作成されませんでした" >&2
exit 1
fi
# ファイルサイズが0より大きいか確認
if [ ! -s "${BACKUP_FILE}" ]; then
echo "Error: バックアップファイルが空です" >&2
exit 1
fi
古いバックアップの削除(サブシェル使用)
bash# 7日以上古いバックアップを削除
# サブシェル内でもset -eを有効にして安全に実行
old_count=$(
set -e
find "${BACKUP_DIR}" -name "*.sql.gz" -mtime +7 -print0 \
| xargs -0 rm -f \
| wc -l
) || {
echo "Warning: 古いバックアップの削除に失敗しました" >&2
}
echo "削除した古いバックアップ: ${old_count}件"
処理完了メッセージ
bash# 成功メッセージ
echo "バックアップが完了しました: ${BACKUP_FILE}"
echo "ファイルサイズ: $(du -h "${BACKUP_FILE}" | cut -f1)"
以下の図で、このスクリプトの処理フローとエラーハンドリングポイントを示します。
mermaidflowchart TD
start["スクリプト開始<br/>set -e, pipefail, -u"] --> mkdir["mkdir -p でディレクトリ作成"]
mkdir --> check1{成功?}
check1 -->|失敗| error1["エラーメッセージ出力<br/>exit 1"]
check1 -->|成功| dump["mysqldump | gzip<br/>でバックアップ"]
dump --> check2{成功?}
check2 -->|失敗| error2["pipefail により<br/>即座に終了"]
check2 -->|成功| verify["バックアップファイル検証"]
verify --> check3{ファイル存在?<br/>サイズ > 0?}
check3 -->|失敗| error3["エラーメッセージ出力<br/>exit 1"]
check3 -->|成功| cleanup["古いバックアップ削除"]
cleanup --> done["完了メッセージ表示"]
error1 --> terminate["スクリプト終了"]
error2 --> terminate
error3 --> terminate
done --> terminate
図で理解できる要点:
- 各ステップでエラーチェックが行われる
- エラー発生時は即座に終了し、後続の危険な処理を防ぐ
pipefailによりパイプライン内のエラーも検出- 検証ステップで、バックアップの成功を確認
実例 2:デプロイスクリプトでの条件分岐
以下は、条件分岐を含むデプロイスクリプトの例です。
環境変数のチェック
bash#!/bin/bash
set -e
set -o pipefail
set -u
# 必須環境変数のチェック
# if文内ではset -eが効かないため、事前にチェック
: "${DEPLOY_ENV:?Error: DEPLOY_ENV が設定されていません}"
: "${APP_NAME:?Error: APP_NAME が設定されていません}"
: "${VAR:?message}" は、変数が未定義または空の場合にエラーメッセージを表示して終了する Bash の機能です。
環境に応じた処理分岐
bash# 環境に応じた設定
if [ "${DEPLOY_ENV}" = "production" ]; then
SERVER_HOST="prod.example.com"
# 本番環境では追加の確認を要求
read -p "本番環境へデプロイします。続行しますか? (yes/no): " confirm
if [ "${confirm}" != "yes" ]; then
echo "デプロイをキャンセルしました"
exit 0
fi
elif [ "${DEPLOY_ENV}" = "staging" ]; then
SERVER_HOST="staging.example.com"
else
echo "Error: 不明な環境: ${DEPLOY_ENV}" >&2
exit 1
fi
ビルドとテストの実行
bash# ビルドの実行(パイプラインでログを保存)
echo "ビルドを開始します..."
yarn build 2>&1 | tee build.log
# ビルド結果の確認
# PIPESTATUSで最初のコマンドの終了ステータスを取得
if [ "${PIPESTATUS[0]}" -ne 0 ]; then
echo "Error: ビルドに失敗しました" >&2
exit 1
fi
PIPESTATUS は、パイプライン内の各コマンドの終了ステータスを配列で保持する Bash の特殊変数です。
テストの実行(失敗時の詳細情報表示)
bash# テストの実行
echo "テストを実行します..."
if ! yarn test; then
# テスト失敗時のエラーコード例
# Error: Test suite failed to run
echo "Error: テストに失敗しました" >&2
echo "詳細: yarn test で1つ以上のテストケースが失敗しました" >&2
exit 1
fi
ファイル転送(サブシェルでの安全な処理)
bash# 成果物を転送
echo "ファイルを転送します: ${SERVER_HOST}"
transfer_result=$(
set -e
set -o pipefail
# rsyncで転送(-aは archive モード、-v は verbose)
rsync -av --delete \
./build/ \
"deploy@${SERVER_HOST}:/var/www/${APP_NAME}/"
# 転送後のファイル数を確認
ssh "deploy@${SERVER_HOST}" \
"ls -1 /var/www/${APP_NAME}/ | wc -l"
) || {
echo "Error: ファイル転送に失敗しました" >&2
echo "エラーコード: $?" >&2
exit 1
}
echo "転送完了: ${transfer_result}件のファイル"
サービスの再起動
bash# アプリケーションの再起動
echo "アプリケーションを再起動します..."
ssh "deploy@${SERVER_HOST}" \
"sudo systemctl restart ${APP_NAME}" || {
echo "Error: systemctl restart ${APP_NAME} が失敗しました" >&2
echo "リモートサーバーでサービスの状態を確認してください" >&2
exit 1
}
# 再起動後のヘルスチェック
sleep 5
health_status=$(
curl -f -s "http://${SERVER_HOST}/health" || echo "unhealthy"
)
if [ "${health_status}" != "ok" ]; then
echo "Error: ヘルスチェックに失敗しました" >&2
echo "レスポンス: ${health_status}" >&2
exit 1
fi
echo "デプロイが完了しました!"
実例 3:エラー処理のまとめとトラップ活用
より高度なエラー処理として、trap コマンドを使った後処理の例を示します。
トラップの設定
bash#!/bin/bash
set -e
set -o pipefail
set -u
# 一時ファイルの初期化
TEMP_DIR=$(mktemp -d)
LOCK_FILE="/var/lock/myapp.lock"
クリーンアップ関数の定義
bash# クリーンアップ関数
# スクリプト終了時(正常/異常問わず)に実行される
cleanup() {
exit_code=$?
echo "クリーンアップを実行中..."
# 一時ファイルの削除
if [ -d "${TEMP_DIR}" ]; then
rm -rf "${TEMP_DIR}"
echo "一時ディレクトリを削除: ${TEMP_DIR}"
fi
# ロックファイルの削除
if [ -f "${LOCK_FILE}" ]; then
rm -f "${LOCK_FILE}"
echo "ロックファイルを削除: ${LOCK_FILE}"
fi
# 終了コードに応じたメッセージ
if [ $exit_code -eq 0 ]; then
echo "正常終了しました"
else
echo "エラーで終了しました(終了コード: $exit_code)" >&2
fi
}
トラップの登録
bash# EXIT シグナル(スクリプト終了時)でクリーンアップを実行
trap cleanup EXIT
# INT シグナル(Ctrl+C)でも適切に終了
trap 'echo "中断されました"; exit 130' INT
メイン処理
bash# ロックファイルの作成(二重起動防止)
if [ -f "${LOCK_FILE}" ]; then
echo "Error: 既に実行中です(ロックファイル: ${LOCK_FILE})" >&2
exit 1
fi
touch "${LOCK_FILE}"
# メイン処理
echo "処理を開始します..."
# ... 実際の処理 ...
echo "処理が完了しました"
# 正常終了(cleanup が自動で実行される)
exit 0
この構造により、スクリプトがどのように終了しても(正常終了、エラー、Ctrl+C による中断など)、必ずクリーンアップ処理が実行されます。
以下の表で、各エラー処理テクニックの使い分けをまとめます。
| # | テクニック | 使用場面 | 効果 |
|---|---|---|---|
| 1 | set -e | すべてのスクリプト | コマンド失敗時の即座の終了 |
| 2 | set -o pipefail | パイプライン使用時 | パイプライン内のエラー検出 |
| 3 | set -u | 変数を多用する場合 | 未定義変数の参照を防止 |
| 4 | command || exit 1 | 条件分岐内 | set -e が効かない場所でのエラー処理 |
| 5 | trap cleanup EXIT | リソース管理が必要な場合 | 終了時の確実なクリーンアップ |
| 6 | PIPESTATUS | パイプラインの詳細チェック | 各コマンドの終了ステータス取得 |
| 7 | : ${VAR:?message} | 必須環境変数のチェック | 変数未設定時の即座の終了 |
まとめ
本記事では、シェルスクリプトにおける set -e の落とし穴と、その回避方法について詳しく解説しました。
set -e は確かに便利なオプションですが、パイプライン処理、サブシェル、条件分岐といった場面では期待通りに動作しないことがあります。これらの状況を理解し、適切な対策を講じることで、堅牢なスクリプトを書けるようになりますね。
特に重要なポイントをおさらいしましょう。
重要ポイント:
set -o pipefailは必須 - パイプライン処理ではset -eだけでは不十分です- サブシェルには注意 - コマンド置換
$(...)内では、エラーが伝播しないケースがあります - 条件分岐では
set -eが無効 -if文や&&/||では明示的なエラーチェックが必要です - 推奨設定セット -
set -euo pipefailを基本として採用しましょう trapでクリーンアップ - リソース管理が必要な場合は、trapを活用して確実にクリーンアップしましょう
これらのテクニックを実践することで、本番環境での予期せぬエラーや、データの不整合を未然に防げます。特にデプロイスクリプトやバックアップスクリプトなど、失敗が許されない場面では、今回紹介したエラー処理を徹底することが重要です。
シェルスクリプトは一見シンプルに見えますが、エラー処理を適切に行うには深い知識が求められます。本記事で紹介した内容を参考に、より安全で信頼性の高いスクリプトを書いていただければ幸いです。
関連リンク
- Bash Reference Manual - The Set Builtin - Bash 公式ドキュメント(set コマンドの詳細)
- POSIX Shell Command Language - POSIX シェル仕様
- ShellCheck - シェルスクリプトの静的解析ツール(エラー検出に有効)
- Google Shell Style Guide - Google のシェルスクリプトスタイルガイド
- Defensive BASH Programming - 堅牢なシェルスクリプトの書き方
articleShell Script の set -e が招く事故を回避:pipefail・サブシェル・条件分岐の落とし穴
articleShell Script でインフラ初期構築の自動化:ユーザー作成・SSH 設定・FW ルール
articleShell Script でファイル操作を極める:find・rsync・圧縮/展開の実践レシピ
articleShell Script 設計 7 原則:可読性・再利用・堅牢性を高める実践ガイド
articleShell Script チートシート:変数・配列・連想配列・算術展開を一枚で把握
articleShell Script 開発環境の作り方:Homebrew・エディタ・シェル選定・PATH 設計
articleKubernetes で WebSocket:Ingress(NGINX/ALB) 設定とスティッキーセッションの実装手順
articleStorybook × Design Tokens 設計:Style Dictionary とテーマ切替の連携
articleWebRTC Simulcast 設計ベストプラクティス:レイヤ数・ターゲットビットレート・切替条件
articleSolidJS コンポーネント間通信チート:Context・イベント・store の選択早見
articleWebLLM 中心のクライアントサイド RAG 設計:IndexedDB とベクトル検索の組み立て
articleShell Script の set -e が招く事故を回避:pipefail・サブシェル・条件分岐の落とし穴
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来