普段利用している自作コマンドを詳解
今回は、普段開発する時に利用している自作コマンドについて共有しようと思います。
Taskfileを伴うプロジェクトの初期化
まずはTaskfile
を利用してプロジェクトを初期化するためのコマンドの紹介です。Taskfile
をタスクランナーとして利用しており、長いコマンド文の省略などに利用しています。利用する言語ごとに大体使う定型分があるので、それをテンプレートとして用意して、コピーしつつ初期化するコマンドを実装しています。Taskfile
については以下で解説しています。
uvのカスタマイズ
Pythonの環境構築はuv
を利用しています。通常であればuv init ...
のような形で初期化しますが、以下のようなコマンドを定義してuv
で初期化しつつTaskfileも用意するようにしています。
function uv_new_with_taskfile() {
if [[ $# -eq 0 ]]; then
echo "Usage: uv_new_with_taskfile <project_name> [uv_init_options...]"
return 1
fi
local project_name=$1
shift
uv init "$project_name" "$@"
if [[ $? -eq 0 ]]; then
cd "$project_name"
uv add --dev ruff pytest mypy
cd ..
cp ./templates/Taskfile_uv.yml $project_name/Taskfile.yml
echo "✅ Created Python project '$project_name' with Taskfile.yml"
else
echo "❌ Failed to create Python project"
return 1
fi
}
# Alias for convenience
alias uvnew="uv_new_with_taskfile"
uv_new_with_taskfile
という関数名で、uv
初期化後にTaskfile
のテンプレートを該当フォルダにコピーするようにしています。呼び出しはuvnew ...
となっており、オプションはuv
と全て同じものとなっております。なお、コピーされるTaskfile
のテンプレートは以下になります。
version: '3'
tasks:
install:
desc: Install dependencies
cmd: uv sync
run:
desc: Run the project
cmd: uv run python -m {{.PROJECT_NAME | default (base .ROOT_DIR)}}
test:
desc: Run tests
cmd: uv run pytest
lint:
desc: Run linter
cmd: uv run ruff check
format:
desc: Format the code
cmd: uv run ruff format
check:
desc: Run type checker
cmd: uv run mypy .
clean:
desc: Clean cache and build artifacts
cmd: |
rm -rf .pytest_cache/
rm -rf __pycache__/
find . -name "*.pyc" -delete
find . -name "*.pyo" -delete
shell:
desc: Activate virtual environment shell
cmd: uv shell
venv:
desc: Create and activate virtual environment
cmd: |
uv venv
source .venv/bin/activate
echo "Virtual environment created and activated"
venv-off:
desc: Deactivate virtual environment
cmd: |
if [ -n "$VIRTUAL_ENV" ]; then
deactivate
echo "Virtual environment deactivated"
else
echo "No virtual environment is currently active"
fi
add:
desc: Add a dependency
cmd: uv add {{.CLI_ARGS}}
remove:
desc: Remove a dependency
cmd: uv remove {{.CLI_ARGS}}
lock:
desc: Update lock file
cmd: uv lock
cargoのカスタマイズ
Rustを使いたい時はcargo
を利用しますが、こちらもuv
と同様にしてコマンドを実装しています。
function cargo_new_with_taskfile() {
if [[ $# -eq 0 ]]; then
echo "Usage: cargo_new_with_taskfile <project_name> [cargo_new_options...]"
return 1
fi
local project_name=$1
shift
# Run cargo new with provided arguments
cargo new "$project_name" "$@"
if [[ $? -eq 0 ]]; then
# Create Taskfile.yml in the new project directory
cp ./templates/Taskfile_cargo.yml $project_name/Taskfile.yml
echo "✅ Created Rust project '$project_name' with Taskfile.yml"
else
echo "❌ Failed to create Rust project"
return 1
fi
}
# Alias for convenience
alias cargonew="cargo_new_with_taskfile"
引数はcargo
のものと一致しております。コマンドはcargonew
という名前で呼び出せるようにしています。コピーするTaskfile
は以下になります。
version: '3'
tasks:
build:
desc: Build the project
cmd: cargo build
run:
desc: Run the project
cmd: cargo run
build_and_run:
desc: Build and run
deps: [build]
cmd: cargo run
test:
desc: Run tests
cmd: cargo test
check:
desc: Check the project for errors
cmd: cargo check
fmt:
desc: Format the code
cmd: cargo fmt
clippy:
desc: Run clippy linter
cmd: cargo clippy
clean:
desc: Clean build artifacts
cmd: cargo clean
release:
desc: Build for release
cmd: cargo build --release
doc:
desc: Generate documentation
cmd: cargo doc --open
Kubernetesのカスタマイズ
kubectl
およびgcloud
を普段利用していますが、コマンドすぐに忘れちゃうので、Taskfile
を利用できるようにコマンドを作りました。
function k8s_with_taskfile() {
if [[ $# -eq 0 ]]; then
echo "Usage: k8s_with_taskfile <project_name> [k8s_new_options...]"
return 1
fi
local project_name=$1
shift
# Create folder
mkdir $project_name
if [[ $? -eq 0 ]]; then
# Create Taskfile.yml in the new project directory
cp ./templates/Taskfile_k8s.yml $project_name/Taskfile.yml
cp ./templates/k8s_sample_pod.yml $project_name/sample-pod.yaml
echo "✅ Created k8s project '$project_name' with Taskfile.yml"
else
echo "❌ Failed to create k8s project"
return 1
fi
}
alias k8snew="k8s_with_taskfile"
ここでコピーするTaskfile
とサンプルのPodを適用するためのファイルは以下になってます。
version: '3'
vars:
CLUSTER_NAME: hoge
SERVER_VERSION: 1.33.1-gke.158400
ZONE: asia-northeast1-a
NUM_NODES: 3
MACHINE_TYPE: n1-standard-4
tasks:
create_cluster:
cmds:
- gcloud container clusters create {{.CLUSTER_NAME}} --cluster-version {{.SERVER_VERSION}} --zone {{.ZONE}} --num-nodes {{.NUM_NODES}} --machine-type {{.MACHINE_TYPE}} --enable-network-policy --enable-vertical-pod-autoscaling
check_server_version:
cmds:
- gcloud container get-server-config --zone {{.ZONE}}
set_cluster_admin:*:
vars:
EMAIL: "{{index .MATCH 0}}"
cmds:
# task set_cluster_admin:hoge@hoge.com
- kubectl create clusterrolebinding user-cluster-admin-binding --clusterrole=cluster-admin --user={{.EMAIL}}
delete_cluster:
cmds:
- gcloud container clust ers delete {{.CLUSTER_NAME}} --zone {{.ZONE}}
apply:
vars:
YAML_FILE: "{{index .MATCH 0}}"
cmds:
- kubectl apply -f {{.YAML_FILE}}
get_pod_yaml:*:
vars:
POD_NAME: "{{index .MATCH 0}}"
cmds:
- kubectl get pod {{.POD_NAME}} -o yaml
list_pods:
cmds:
- kubectl get pods
list_pods_detail:
cmds:
- kubectl get pods --output wide
exec_bash:*:
vars:
POD_NAME: "{{index .MATCH 0}}"
cmds:
- kubectl exec -it {{.POD_NAME}} -- /bin/bash
apiVersion: v1
kind: Pod
metadata:
name: sample-pod
spec:
containers:
- name: nginx-container
image: nginx:1.16
pecoの応用
peco
を普段結構利用しているのですが、|
でコマンド結果を受け渡したりするのがめんどくさかったのでpeco ...
という形式でファイル入力からコマンド実行結果まで全部受け渡したいなと思って、peca
というコマンドでそれができるようにしてみました。
function peca() {
if [ $# -eq 0 ]; then
echo "Usage: peca <file_or_command> [args...]"
echo "If argument is a file, cat it and pipe to peco"
echo "Otherwise, execute command and pipe output to peco"
return 1
fi
local first_arg="$1"
shift
if [ -f "$first_arg" ]; then
cat "$first_arg" | peco
elif [ -e "$first_arg" ]; then
echo "Error: $first_arg exists but is not a regular file"
return 1
else
local cmd="$first_arg $*"
local output
output=$(eval "$cmd" 2>&1)
local exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "Command failed with exit code $exit_code:"
echo "$output"
return $exit_code
fi
if [ -z "$output" ]; then
echo "No output from command"
return 0
fi
echo "$output" | peco
fi
使い方としては以下のようにファイルからコマンド結果までなんでもいけます。
peca hoge.csv
peca ls -la
まとめ
今回は私が普段よく使ってる自作コマンドについて紹介しました。シェルスクリプトはまだまだ下手でAIの協力とかももらいつつコマンド実装方法を日々調べて実装しています。みなさんのおすすめの自作コマンドもあればいろいろ教えてくれると嬉しいです。
Discussion