Skip to main content

4 posts tagged with "cli"

View All Tags

알아두면 쓸데있는 개발자 도구 - CLI 편

· 10 min read
Haril Song
Owner, Software Engineer at 42dot

Overview

최고의 App 을 설명했던 지난 글 에 이어서 Command Line Interface(이하 CLI) 중 추천할만한 도구를 살펴본다. 이번에 소개되는 모든 툴들은 필자가 최소 6개월 이상 써본 도구들이며, 새로운 장비를 설정할 때 반드시 설치하는 것들이다.

zoxide

GitHub - ajeetdsouza/zoxide: A smarter cd command. Supports all major shells.

한 번이라도 방문했던 디렉토리라면 경로를 기억할 필요가 없게 해주는 툴. 예를 들면 아래와 같은 경우다.

cd ~/.config/somewhere/longlong/path

# 다음부터는 아래 명령으로 바로 방문가능
z path

이게 굉장히 편리해서, 특정 설정 파일이 어디있는지 기억할 필요가 없어진다. zi 를 사용하면 우선순위 List 가 출력되기 때문에, fuzzy 하게 찾아갈 수도 있다.

한 번 써보면 다시는 이 툴을 사용하기 전으로 돌아갈 수 없을 것.

mise

GitHub - jdx/mise: dev tools, env vars, task runner

각종 환경변수 및 언어, 패키지들의 버전 매니저. 구조상 안정성이 매우 뛰어나며, Rust 로 구현되어 속도도 빠르다. 직관적인 명령어는 러닝커브를 크게 완화시켜 준다.

이미 본 블로그에 글로도 소개했을만큼, 굉장히 애정하는 툴이다. mise 역할을 해줄 비슷한 도구는 몇가지 더 있지만 개인적으로는 그 중 가장 추천할만하다고 생각한다. 예를 들면, direnv 는 mise 로 완전히 대체가 가능하고 nix 는 과하게 복잡하여 범용성이 떨어진다.

다양한 언어를 다루는 프로그래밍 Multilingual 이라면, 꼭 써보자.

chezmoi

chezmoi

사용하는 장비가 여러 대라면, 개발 환경을 동기화하기가 여간 귀찮은게 아니다. 특히 CLI 를 자주 사용하는 개발자라면 더더욱.

아예 동기화를 포기하고 지낼 생각이라면 모르겠지만, 어떻게 동기화할 수 있을지 고민하고 있다면 chezmoi 를 써보자. 혹여, 새로운 장비를 구매하더라도 초기 설정에 시간을 들일 필요가 없어진다.

mise 와 마찬가지로 본 블로그에 사용법에 관한 이 있으니 참고.

fzf

GitHub - junegunn/fzf: :cherry_blossom: A command-line fuzzy finder

GitHub Star 약 70k, 더 이상의 설명이 필요할까(참고로 spring-framework 가 57k 이다).

한국인 개발자인 junegunn 님께서 관리하시는 오픈소스 fuzzy finder 로, 표준입출력 파이프라이닝을 통해 어마어마한 범용성을 자랑한다.

검색이 필요하다면, 종류에 상관없이 fzf 를 쓰면 된다. 워낙 이런저런 패키지들이 가져다가 쓰는 중이라, fzf 의 존재를 몰랐더라도 이미 간접적으로 쓰고 있었을 수 있다.

fd

GitHub - sharkdp/fd: A simple, fast and user-friendly alternative to 'find'

find 명령을 대체한다.

Rust 로 작성되었으며, find 에 비해 최대 50% 빠르다고 한다. highlighting 도 깔끔한 편이고, 명령어 옵션도 find 보다 훨씬 직관적이다.

ripgrep

GitHub - BurntSushi/ripgrep: ripgrep recursively searches directories for a regex pattern while respecting your gitignore

grep 명령을 대체한다. 이름은 ripgrep 이지만 rg 를 명령어로 사용한다.

fd 와 비슷하게, Rust 로 작성되었다. grep 에 비해 출력으로 훨씬 다양한 정보를 얻을 수 있다. 명령어도 직관적이라 사용도 쉬운데 속도까지 빠르니 안쓸 이유가 딱히 없다.

그야말로 'RIP, grep'.

lsd

GitHub - lsd-rs/lsd: The next gen ls command

ls 명령을 대체한다.

ls 명령은 어마어마하게 많이 쓰는 명령이다. 명령어 자체가 오래되었기도 하지만, 출력으로 알 수 있는 정보가 다양하지는 않다. lsd 를 사용하면 기존 ls 를 완전히 대체할 수 있다.

bat

GitHub - sharkdp/bat: A cat(1) clone with wings.

cat 명령을 대체한다.

cat 명령은 단순 출력이지만, bat 을 사용하면 code highlighting 을 누릴 수 있다. 어느 정도 눈치 빠른 개발자라면 라인 출력을 보고 '쉘 파이프라이닝을 방해하는거 아닐까' 걱정이 될 수 있지만, 전혀 방해하지 않는다. 걱정말고 신문물을 누려보자.

필자는 bat 명령의 alias 를 cat 으로 설정하여 사용하고 있다.

HTTPie

HTTPie – API testing client that flows with you

curl 을 대체한다.

APP 도 있어서 어느 글에 포함시켜야할까 고민을 했지만, 개인적으로는 cli 로만 사용하기 때문에 이쪽 글로 넣었다.

curl 대신 HTTPie 를 선호하냐하면, 매우매우 직관적이기 때문이다. 간단한 GET 요청은 아래처럼 보낼 수 있다.

https httpie.io/hello

응답은 이렇게 포맷팅되어 온다.

curl 응답을 떠올려보자. 개발자도 예쁜걸 좋아한다.

Orbstack

OrbStack · Fast, light, simple Docker & Linux

Docker Desktop 을 대체한다.

Docker 컨테이너를 사용할 때 조금 더 빨라지고 몇몇 버그들이 사라진다. 하지만 진정한 진가는 VM 을 사용할 때인데, 전통적으로 VM 을 쓰기 어려웠던 맥에서 VM 을 굉장히 가볍게 실행시킬 수 있다. 우분투나 칼리리눅스 등의 OS 에서 테스트가 필요할 경우, orbstack 을 사용하면 매우 빠르고 편리하게 관리할 수 있으니 사용해보자. 개인적으로 매우 재밌는 경험이었다.

atuin

GitHub - atuinsh/atuin: ✨ Magical shell history

chezmoi 를 사용하면 사용하는 도구들의 설정은 동기화할 수 있었다. atuin 을 사용하면 회사에서 쳤던 명령어 history 를 동기화할 수 있다. 더 이상 회사에서 사용했던 명령어가 뭐였는지 기억해내려고 안간힘을 쓸 필요가 없다.

warning

한가지 아쉬운 점은 터미널로 Warp 를 사용한다면 온전히 atuin 을 활용하기 어렵다는 점이다. Warp 는 자체 history 기능을 제공하여 atuin 과 간섭이 있다. 아래 명령을 사용하면 history 에서 명령어 검색이 가능하여, 임시방편으로 쓰고 있다.

atuin history list | fzf

trash-cli

터미널에 '휴지통' 기능을 구현한다. 따라서 더 이상 rm -rf / 을 두려워할 필요가 없어진다. 얼마든지 복원이 가능하기 때문.

개발자 최대의 적인 rm -rf / 에서 자유로워질 수 있다는데, 그 이상의 이유가 필요한가?

Conclusion

지금까지 개인적으로 매우 좋아하는 여러 툴들을 소개했다.

사실 이 외에도 추천할만한 도구는 얼마든지 더 있지만, 누가 뭘 추천해주든 자기 손에 익은게 제일 좋은 법이다. 나머지는 자신의 환경에 맞게 찾아써보자.

info

사용 중인 모든 툴은 여기서 볼 수 있다.

Managing Environment Variables with AWS S3 and Automation

· 5 min read
Haril Song
Owner, Software Engineer at 42dot

Situation

  • As the codebase grows, the number of configuration values required for running a Spring application is increasing.
  • While most situations are validated with test code, there are times when testing with bootRun locally is necessary.

Complication

  • Want to separate configuration values into environment variables for better management.
  • .env files are typically ignored in Git, making version tracking difficult and prone to fragmentation.
    • Need a way to synchronize files across multiple machines.

Question

  • Is there a convenient method that minimizes friction among developers and is easy to apply?
    • Preferably a familiar method for easier maintenance.
  • Can the version of .env files be managed?
  • Is the learning curve low?
    • Want to avoid a situation where the solution is more complex than the problem.
  • Can it be applied directly to the production environment?

Answer

AWS S3

  • Updating .env files is convenient with AWS CLI.
  • Version control of .env files can be done through snapshots.
  • AWS S3 is a service familiar to most developers and has a low learning curve.
  • In the AWS ECS production environment, system variables can be directly applied using S3 ARNs.

.

..

...

....

Is that all?

If that's it, the article might seem a bit dull, right? Of course, there are still a few issues remaining.

Which Bucket is it in?

When using S3, it's common to end up with many buckets due to file structure optimization or business-specific categorization.

aws s3 cp s3://something.service.com/enviroment/.env .env

If the .env file is missing, you'll need to download it using AWS CLI as shown above. Without someone sharing the bucket with you in advance, you might have to search through all buckets to find the environment variable file, which could be inconvenient. The intention was to avoid sharing, but having to receive something to share again might feel a bit cumbersome.

Too many buckets. Where's the env...?

Automating the process of exploring buckets in S3 to find and download the necessary .env file would make things much easier. This can be achieved by writing a script using tools like fzf or gum.

Spring Boot Requires System Environment Variables, Not .env...

Some of you may have already noticed that Spring Boot reads system environment variables to fill in placeholders in YAML files. However, using just the .env file won't apply the system environment variables, thus not being picked up during Spring Boot's initialization process.

Let's briefly look at how it works.

# .env
HELLO=WORLD
# application.yml
something:
hello: ${HELLO} # Retrieves the value from the HELLO environment variable on the OS.
@Slf4j
@Component
public class HelloWorld {

@Value("${something.hello}")
private String hello;

@PostConstruct
public void init() {
log.info("Hello: {}", hello);
}
}

SystemEnvironmentPropertySource.java

You can see that the placeholder in @Value is not resolved, causing the bean registration to fail and resulting in an error.

Just having a .env file doesn't register it as a system environment variable.

To apply the .env file, you can either run the export command or register the .env file in IntelliJ's run configurations. However, using the export command to register too many variables globally on your local machine can lead to unintended behavior like overwriting, so it's recommended to manage them individually through IntelliJ's GUI.

IntelliJ supports configuring .env files via GUI.

The placeholder is resolved and applied correctly.

Final Answer - The Real Final One

Phew, the long process of problem identification and scoping has come to an end. Let's summarize the workflow once more and introduce a script.

  1. Use an automation script to find and download the appropriate .env from S3.
  2. Set the .env as system environment variables.

The shell script is written to be simple yet stylized using gum.

Full Code

#!/bin/bash

S3_BUCKET=$(aws s3 ls | awk '{print $3}' | gum filter --reverse --placeholder "Select...") # 1.

# Choose deployment environment
TARGET=$(gum choose --header "Select a environment" "Elastic Container Service" "EC2")
if [ "$TARGET" = "Elastic Container Service" ]; then
TARGET="ecs"
else
TARGET="ec2"
fi

S3_BUCKET_PATH=s3://$S3_BUCKET/$TARGET/

# Search for the env file
ENV_FILE=$(aws s3 ls "$S3_BUCKET_PATH" | grep env | awk '{print $4}' | gum filter --reverse --placeholder "Select...") # 2.

# Confirm
if (gum confirm "Are you sure you want to use $ENV_FILE?"); then
echo "You selected $ENV_FILE"
else
die "Aborted."
fi

ENV_FILE_NAME=$(gum input --prompt.foreground "#04B575" --prompt "Enter the name of the env file: " --value ".env" --placeholder ".env")
gum spin -s meter --title "Copying env file..." -- aws s3 cp "$S3_BUCKET_PATH$ENV_FILE" "$ENV_FILE_NAME" # 3.

echo "Done."
  1. Use gum filter to select the desired S3 bucket.
  2. Search for items containing the word env and assign it to a variable named ENV_FILE.
  3. Finalize the object key of the .env file and proceed with the download.

I've created a demo video of the execution process.

Demo

After this, you just need to apply the .env file copied to the current directory to IntelliJ as mentioned earlier.

tip

Using direnv and IntelliJ's direnv plugin can make the application even more convenient.

Conclusion

  • The script is easy to maintain due to its simplicity.
  • Team response has been very positive.
  • Developers appreciate aesthetics.
  • For sensitive credentials, consider using AWS Secret Manager.

Managing Google Kubernetes Engine through Local CLI

· 3 min read
Haril Song
Owner, Software Engineer at 42dot

Overview

While it is very convenient to be able to run kubectl through Google's Cloud Shell via the web from anywhere, there is a drawback of needing to go through the hassle of web access and authentication for simple query commands. This article shares a method for quickly managing Google Cloud Kubernetes using a local CLI.

Contents

Installing GCP CLI

First, you need to install the GCP CLI. Refer to the gcp-cli link to check for the appropriate operating system and install it.

Connection

Once the installation is complete, proceed with the authentication process using the following command:

gcloud init

You need to access the GCP Kubernetes Engine and fetch the connection information for the cluster.

GKE-connect

gke-cluster-connect-2

Copy the command for command-line access and execute it in the terminal.

gcloud container clusters get-credentials sv-dev-cluster --zone asia-northeast3-a --project {projectId}
Fetching cluster endpoint and auth data.
CRITICAL: ACTION REQUIRED: gke-gcloud-auth-plugin, which is needed for continued use of kubectl, was not found or is not executable. Install gke-gcloud-auth-plugin for use with kubectl by following https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke
kubeconfig entry generated for sv-dev-cluster.

Plugin Installation

If the current Kubernetes version being used is below v1.26, you may encounter an error requesting the installation of gke-gcloud-auth-plugin. Install the plugin using the following command.

info

Prior to v1.26, client-specific code for managing authentication between the client and Google Kubernetes Engine was included in the existing versions of kubectl and custom Kubernetes clients. Starting from v1.26, this code is no longer included in the OSS kubectl. GKE users need to download and use a separate authentication plugin to generate GKE-specific tokens. The new binary, gke-gcloud-auth-plugin, extends the kubectl authentication for GKE using the Kubernetes Client-go user authentication information plugin mechanism. Since the plugin is already supported in kubectl, you can switch to this new mechanism before v1.26 is provided. - Google

gcloud components install gke-gcloud-auth-plugin
Your current Google Cloud CLI version is: 408.0.1
Installing components from version: 408.0.1

┌────────────────────────────────────────────┐
│ These components will be installed. │
├────────────────────────┬─────────┬─────────┤
│ Name │ Version │ Size │
├────────────────────────┼─────────┼─────────┤
│ gke-gcloud-auth-plugin │ 0.4.0 │ 7.1 MiB │
└────────────────────────┴─────────┴─────────┘

For the latest full release notes, please visit:
https://cloud.google.com/sdk/release_notes

Do you want to continue (Y/n)? y

╔════════════════════════════════════════════════════════════╗
╠═ Creating update staging area ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: gke-gcloud-auth-plugin ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: gke-gcloud-auth-plugin ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Creating backup and activating new installation ═╣
╚════════════════════════════════════════════════════════════╝

Performing post processing steps...done.

Update done!

re-run the connection command, and you should see that the cluster is connected without any error messages.

gcloud container clusters get-credentials sv-dev-cluster --zone asia-northeast3-a --project {projectId}
Fetching cluster endpoint and auth data.
kubeconfig entry generated for sv-dev-cluster.

Once the connection is successful, you will also notice changes in Docker Desktop. Specifically, new information will be displayed in the Kubernetes tab.

1.png

Afterwards, you can also directly check GKE resources locally using kubectl.

kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
my-application 1/1 1 1 20d

Conclusion

We have briefly explored efficient ways to manage GKE resources locally. Using kubectl locally enables extended features like autocomplete, making Kubernetes management much more convenient. If you are new to using GKE, I strongly recommend giving it a try.

Reference

k8s-plugin

Elegant HTTP CLI, HTTPie

· 2 min read
Haril Song
Owner, Software Engineer at 42dot

Overview

CLI tool that can replace the curl command

If you are a developer who frequently uses Linux, you probably use the curl command often. It is an essential command for sending external API requests from a server, but it has the disadvantage of poor readability in the output. HTTPie is an interesting tool that can alleviate this drawback, so let's introduce it.

Install

For Mac users, you can easily install it using brew.

brew install httpie

For CentOS, you can install it using yum.

yum install epel-release
yum install httpie

Usage

First, here is how you would send a GET request using curl.

curl https://httpie.io/hello

curl-get

Now, let's compare it with HTTPie.

https httpie.io/hello

get

The readability is much better in every aspect of the command. The response and header values are included by default, so you can get various information at a glance without using separate commands.

Note that https and http are distinguished in the command.

http localhost:8080

You can send a POST request as described on the official website.

http -a USERNAME POST https://api.github.com/repos/httpie/httpie/issues/83/comments body='HTTPie is awesome! :heart:'

Various other features are explained on GitHub, so if you make good use of them, you can greatly improve productivity.

Reference