Community라이팅 & 에디팅github.com

pwquint24/org-babel-shell

시스템 자동화, DevOps, 원격 실행, 셸 스크립팅(Bash, Zsh, Fish, Dash, Sh)을 위한 Org Babel 종합 가이드입니다.

org-babel-shell란 무엇인가요?

이 스킬은 Org Babel에서 셸 코드 블록을 사용하는 방법에 대한 포괄적인 가이드를 제공합니다. Org Mode를 대화형 DevOps 노트북, runbook, 시스템 관리 콘솔로 변환하여 Bash, Zsh, Fish, Dash, Sh, Csh, Ksh, Ash 등 다양한 셸을 지원합니다. 격리된 서브셸 실행, 세션 기반 대화형 실행, 비동기 실행 등 다양한 실행 모드를 제공하며, `:stdin`, `:cmdline`, `:shebang`과 같은 셸 전용 헤더 인자를 통해 표준 입력 파이핑, 명령줄 인수 전달, 독립 실행형 스크립트 실행을 가능하게 합니다. 또한 TRAMP(`:dir`)를 통한 원격 서버 관리, 결과 포맷(Org 테이블, 파일 링크), 변수 및 배열 전달 기능을 지원하여 DevOps 워크플로우 전반에 걸쳐 강력하고 유연한 셸 기반 자동화를 구현할 수 있습니다. 개발자, 시스템 관리자, DevOps 엔지니어가 Emacs 환경 안에서 스크립트를 작성하고 실행하며 시스템을 관리하는 데 탁월한 효율성을 제공합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/pwquint24/org-babel-agent-skills/tree/HEAD/skills/org-babel-shell

Installed? Explore more 라이팅 & 에디팅 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Org Babel의 셸 및 Bash 코드 블록

Org Babel은 Unix 및 POSIX 셸(Bash, Zsh, Sh, Fish, Dash, Csh, Ksh, Ash) 전반에 걸쳐 포괄적인 셸 스크립팅을 지원합니다.

셸 블록은 Org Mode를 로컬 실행, 백그라운드 비동기 처리, TRAMP를 통한 SSH 기반 원격 서버 관리가 가능한 대화형 DevOps 노트북, runbook, 시스템 관리 콘솔로 변환합니다.


1. 요구 사항 및 설정

1.1 Emacs 설정

별도의 모듈이 필요한 다른 Babel 언어와 달리, 모든 셸은 단일 Babel 라이브러리(ob-shell)로 관리됩니다. org-babel-load-languages에 (shell . t)만 추가하면 됩니다:

(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (shell      . t)))

(참고: Org 8.2 이전에는 sh로 명명되었습니다. 모든 최신 Org 버전에서는 shell을 사용하십시오).

1.2 셸 지정

블록 언어 태그(#+BEGIN_SRC <shell>)에 정확한 셸 바이너리 이름을 지정하십시오:

# Bash:
#+BEGIN_SRC bash
  echo "Running in $BASH_VERSION"
#+END_SRC

# Zsh:
#+BEGIN_SRC zsh
  echo "Running in Zsh $ZSH_VERSION"
#+END_SRC

# POSIX / Dash (더 빠르고 가벼운 실행):
#+BEGIN_SRC dash
  echo "Running in dash"
#+END_SRC

# Fish 셸:
#+BEGIN_SRC fish
  set greeting "Hello from fish"
  echo $greeting
#+END_SRC

지정된 셸 바이너리는 시스템 $PATH에서 접근 가능해야 합니다.


2. 실행 모드: 격리, 세션, 비동기

2.1 격리된 서브셸 (기본값, :session none)

각 블록은 새로운 임시 서브셸 프로세스에서 실행됩니다. 환경 변수와 작업 디렉토리는 유지되지 않습니다:

#+BEGIN_SRC bash :results output
  echo "PID: $$"
  export WORKSPACE="/tmp/build"
#+END_SRC

#+BEGIN_SRC bash :results output
  # 새로운 서브셸 프로세스에서 실행되므로 $WORKSPACE는 비어 있습니다:
  echo "PID: $$, WORKSPACE: $WORKSPACE"
#+END_SRC

2.2 대화형 세션 (:session <name>)

지속적인 Emacs comint 버퍼(예: *dev-session*) 내에서 실행됩니다. 변수, 함수, 작업 디렉토리가 여러 블록에 걸쳐 유지됩니다:

#+BEGIN_SRC bash :session *dev-session* :results output
  export CLUSTER_ID="prod-east-01"
  cd /var/log
#+END_SRC

#+BEGIN_SRC bash :session *dev-session* :results output
  # 이전 블록에서 설정된 상태를 사용합니다:
  echo "Deploying to $CLUSTER_ID from $(pwd)"
#+END_SRC

#+RESULTS:
: Deploying to prod-east-01 from /var/log

2.3 비차단 비동기 실행 (:async yes)

백업, 컨테이너 빌드, 모델 학습과 같은 장기 실행 스크립트는 동기적으로 실행될 때 Emacs를 멈추게 합니다. :async yes를 추가하여 편집기를 잠그지 않고 백그라운드에서 실행하세요!

규칙:

  1. :async는 :session <name>이 필수입니다.
  2. 실행 중에 Babel은 임시 UUID 토큰을 #+RESULTS: 블록에 삽입합니다.
  3. 백그라운드 실행이 완료되면 UUID가 자동으로 명령의 표준 출력으로 대체됩니다.
#+BEGIN_SRC bash :session *bg-job* :async yes :results output
  echo "Starting heavy database backup at $(date)..."
  sleep 5
  echo "Backup finished successfully at $(date)!"
#+END_SRC

#+RESULTS:
: Starting heavy database backup at Sun May 18 14:00:00 UTC 2025...
: Backup finished successfully at Sun May 18 14:00:05 UTC 2025!

세션에서 동기적으로 실행하려면 :async no를 전달하십시오.


3. 셸 전용 헤더 인자

Org Babel은 셸 작업에 특화된 세 가지 고유한 헤더 인자를 제공합니다:

3.1 :stdin <요소-이름> (표준 입력)

Org 요소(테이블, 원시 텍스트 또는 다른 코드 블록 결과)를 셸 명령의 stdin으로 파이프합니다:

# 원시 텍스트 입력:
#+NAME: raw_server_payload
{"node": "alpha", "cores": 8, "status": "active"}

# jq로 직접 페이로드 파이프:
#+BEGIN_SRC bash :stdin raw_server_payload :results output
  jq -r '.node + " has " + (.cores|tostring) + " cores"'
#+END_SRC

#+RESULTS:
: alpha has 8 cores

(참고: :stdin을 사용하는 블록은 임시 서브셸에서 평가되며 :session을 무시합니다).

3.2 :cmdline <인수> (명령줄 인수)

위치 인수($1, $2, $@)를 스크립트 본문에 전달합니다:

#+BEGIN_SRC bash :cmdline "staging" 8080 :results output
  ENV="$1"
  PORT="$2"
  echo "Starting server on port $PORT in $ENV mode..."
#+END_SRC

#+RESULTS:
: Starting server on port 8080 in staging mode...

⚠️ 보안 경고: :cmdline 인수는 호스트 셸에 의해 직접 확장됩니다. 명령 주입을 방지하려면 신뢰할 수 없거나 이스케이프되지 않은 문자열을 전달하지 마십시오.

3.3 :shebang <지시문> (독립 실행형 스크립트 및 깔끔한 출력)

블록을 임시 실행 파일로 작성하고 shebang 지시문을 통해 실행하도록 강제합니다:

#+BEGIN_SRC bash :shebang "#!/usr/bin/env bash" :results output
  for i in {1..3}; do
      echo "Step $i"
  done
#+END_SRC

:shebang이 중요한 이유: shebang이 없는 여러 줄 :session 블록에서는 줄이 대화형 셸로 한 줄씩 전송되어 결과에 불필요한 프롬프트 문자열(예: bash-5.1$ )이 나타날 수 있습니다. :shebang을 지정하거나 세션 없이 실행하면 완전히 깔끔한 출력이 생성됩니다.


4. TRAMP를 통한 원격 서버 관리 (:dir)

:dir에 TRAMP 경로를 지정하여 원격 서버, 가상 머신 또는 Docker 컨테이너에서 명령을 실행할 수 있습니다:

:dir /ssh:<사용자>@<호스트>:<원격-경로>
:dir /docker:<컨테이너-id>:<경로>
:dir /sudo::/etc

예: 원격 Sysadmin 워크플로우

# 원격 서버의 디스크 사용량 및 메모리 확인:
#+BEGIN_SRC bash :dir /ssh:[email protected]:/tmp :results output
  hostname
  uptime
  df -h / | awk 'NR==2 {print "Root Disk Usage: " $5}'
#+END_SRC

#+RESULTS:
: bastion.example.com
: 14:22:05 up 42 days,  3:18,  1 user,  load average: 0.12, 0.08, 0.05
: Root Disk Usage: 48%

원격 세션

:dir와 :session을 결합하여 각 단계마다 다시 연결하지 않고 여러 블록에 걸쳐 활성 SSH 연결을 유지합니다:

#+BEGIN_SRC bash :dir /ssh:[email protected]:/home/admin :session *remote-bastion* :results output
  WORKDIR=$(mktemp -d)
  cd "$WORKDIR"
  pwd
#+END_SRC

5. 결과 형식 및 표 형식 데이터 추출

5.1 탭으로 구분된 출력을 Org 테이블로 (:results output table)

셸 명령이 탭으로 구분되거나 구조화된 표 형식 출력을 내보내면 Babel이 이를 기본 Org 테이블로 파싱합니다:

#+BEGIN_SRC bash :results output table
  printf "PID\tUser\tCommand\n"
  printf "101\troot\tsystemd\n"
  printf "405\tpostgres\tpostgres\n"
  printf "892\tnginx\tnginx: worker\n"
#+END_SRC

#+RESULTS:
| PID | User     | Command       |
|-----+----------+---------------|
| 101 | root     | systemd       |
| 405 | postgres | postgres      |
| 892 | nginx    | nginx: worker |

5.2 출력을 파일 링크로 전환 (:results file :file <경로>)

#+BEGIN_SRC bash :results file :file reports/sysinfo.txt
  uname -a > reports/sysinfo.txt
  cat /etc/os-release >> reports/sysinfo.txt
#+END_SRC

#+RESULTS:
[[file:reports/sysinfo.txt]]

6. 변수 및 Bash 배열 전달 (:var)

6.1 스칼라 및 문자열

#+BEGIN_SRC bash :var port=8000 host="localhost" :results output
  echo "Connecting to $host on port $port..."
#+END_SRC

6.2 Bash 1D 배열

Bash는 리스트 구문으로 정의된 1차원 배열 매개변수를 지원합니다:

#+BEGIN_SRC bash :results output :var servers='("web-01" "web-02" "db-01")'
  echo "Total servers: ${#servers[@]}"
  for s in "${servers[@]}"; do
      echo "Pinging $s..."
  done
#+END_SRC

#+RESULTS:
: Total servers: 3
: Pinging web-01...
: Pinging web-02...
: Pinging db-01...

7. 일반적인 함정 및 안전 모범 사례

함정원인해결책
Emacs가 SSH 또는 ffmpeg 명령에서 멈춤명령이 서브셸에서 stdin을 읽으려고 시도stdin을 명시적으로 리디렉션(</dev/null)하거나 ssh -n 사용
결과에 bash-5.1$ 프롬프트 문자가 나타남:session에서 대화형 줄 단위 에코:shebang #!/usr/bin/env bash 추가 또는 세션 외부에서 평가
heredoc에서 의도하지 않은 변수 확장<<EOF를 사용하면 셸이 $VARS를 조기에 확장구분 기호를 인용 처리한 <<"EOF"를 사용하여 텍스트를 리터럴로 유지하고 조기 확장 방지
sh 블록에서 POSIX 외 구문 실패#+BEGIN_SRC sh는 /bin/sh(종종 Debian/Ubuntu에서는 dash)로 매핑스크립트가 bashism([[, ((, 배열)을 사용하는 경우 #+BEGIN_SRC bash 사용
:cmdline을 통한 명령 주입셸 인수가 그대로 평가됨인수를 신중하게 인용하거나 :stdin 또는 :var를 통해 데이터 전달
비동기 블록 출력이 나타나지 않음:async yes에는 활성 :session이 필요:async yes를 사용할 때 항상 :session <name> 제공

8. 완전한 DevOps Runbook 예제

#+TITLE: 프로덕션 서비스 상태 Runbook
#+PROPERTY: header-args:bash :session *runbook* :results output

* 1단계: 상태 확인 설정
#+NAME: cluster_nodes
| Hostname        | Role    |
|-----------------+---------|
| prod-app-01.lan | backend |
| prod-app-02.lan | backend |
| prod-db-01.lan  | storage |

* 2단계: 클러스터 노드 프로브
#+BEGIN_SRC bash :var nodes=cluster_nodes :colnames yes :results output table
  printf "Host\tRole\tStatus\n"
  for row in "${nodes[@]}"; do
      # 탭/공백으로 구분된 행 데이터 파싱:
      host=$(echo "$row" | awk '{print $1}')
      role=$(echo "$row" | awk '{print $2}')
      
      # 빠른 ping 프로브:
      if ping -c 1 -W 1 "$host" > /dev/null 2>&1; then
          status="ONLINE"
      else
          status="OFFLINE"
      fi
      printf "%s\t%s\t%s\n" "$host" "$role" "$status"
  done
#+END_SRC

#+RESULTS:
| Host            | Role    | Status |
|-----------------+---------+--------|
| prod-app-01.lan | backend | ONLINE |
| prod-app-02.lan | backend | ONLINE |
| prod-db-01.lan  | storage | ONLINE |

* 3단계: 서비스 유지보수를 비동기로 실행
#+BEGIN_SRC bash :session *runbook* :async yes
  echo "Initiating rolling cache purge across nodes..."
  sleep 4
  echo "Cache purge completed successfully."
#+END_SRC

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

관련 스킬