카일 스쿨 4회차

  • Hits
  • #0. 질문 잘 하는 방법
  • #1. 저번 주 간단 복습
  • #2. 쉘 커맨드
  • #3. 쉘 스크립트

질문 잘 하는 방법

  • 우리는 이미 많은 곳에서 질문을 함
  • 크게 두가지 소스
    • 오프라인 : 회사에서 사수,멘토, 팀장님 등
    • 온라인 : 온라인 커뮤니티 및 메일 문의
  • 둘 다 질문 잘하는 방법이 매우 중요함
  • 공통적으로 중요한 부분
    • 바보 같은 질문은 없다고 생각하기. 질문해도 충분히 괜찮다. 지금 모른다고 부끄러운 일이 아니고, 내가 실수하는 것을 다른 사람도 할 수 있다
    • 무엇을 물어볼 것인가? 구체적으로 생각해보기
      • 좋지 않은 질문 : 이거 안되요. 설치가 안되요.
    • 왜 그 현상이 발생했나? 고민해보기
    • 어떤 환경에서 실행했는가?
    • Error 메세지는 무엇이 나왔나?
      • 그 Error 메세지를 해결하기 위해 어떤 노력을 했는가?
    • 재현이 가능해야 함
    • 질문을 통해 해결했다면 그 내용을 정리해두기(팀을 위해 정리해서 공유해도 좋음)
  • 오프라인에서
    • 누구에게 물어볼 것인가?
    • 질문하는 것은 상대방의 시간 리소스를 사용하는 것
      • 따라서 상대방의 성향을 파악해봐야 함
      • "아무 시간이나 질문해도 되는지?" : 자신이 주로 업무할 때 질문 받는것을 싫어하는 경우도 있음
      • 싫어한다면 따로 시간을 내달라고 요청하는 것도 좋은 방법
      • "질문의 퀄리티를 중요하게 여기는 경우"
      • "같은 질문을 좋아하지 않는 경우"
      • 카일은?
    • 작은 감사 표현 => 사람인지라 그런 것들이 보이면 더 신경써주게 됨
    • 중요한 부분 : 누구에게나 잘 질문하는 문화인지 확인해보기
  • 온라인
    • 어떤 커뮤니티에 할 것인가? or 어떤 분에게 메일을 보낼 것인가?
    • 어떤 맥락으로 하는지
      • ~~~를 하는데 이게 여기서 많이 이야기되서?
      • 이 내용으로 검색하니 블로그를 봤고 감사의 인사
    • Code Snippet
      • gist.github.com 을 이용해 코드를 전달드리고, 적절한 스크린샷 첨부시 좋음
    • 단순 고민 토로식 질문은 좋은 답변이 오지 않을 확률이 큼
    • 예의!
  • 질문의 좋은 점
    • 좋은 질문을 준비하는 동안 깨달음과 실력 향상에 도움을 줌
    • 함께 자라기의 실천
  • 그리고 추가로
    • 신입일 때 의사결정이나 어려운 내용이 자주 있을 수 있음
    • => 그럴때 도와주라고 팀장님들이 있으니 고민이 있으면 나누고, 이슈 해결한다고 보면 됨니다

저번 주 간단 복습

  • 쉘을 사용해야 하는 이유
  • 리다이렉트
  • 표준스트림
  • grep
  • cat
  • ps

쉘 커맨드

  • 지난 시간에 다루지 못한 쉘 커맨드
  • awk

    • 데이터를 조작하고 레포트를 생성하기 위해 사용하는 명령어
    • Alfred Aho, Peter Weinberger, Brian Kernighan 3명이 만들었는데 이니셜을 가져와 awk라 부름
    • awk는 명령어를 입력한 다음, 작은 따옴표로 둘러싸인 패턴/액션을 입력하고 마지막에 입력 파일을 지정

      awk 'pattern' filename
      awk '{action}' filename
      awk 'pattern {action}' filename
  • awkfile

      vi awkfile
    
      홍 길동 3324    5/11/96 50354  
      임 꺽정 5246    15/9/66 287650  
      이 성계 87654    6/20/58 60000  
      정 약용 908683    9/40/48 365000
  • awk '{print $0}' awkfile

    • 전체 print

      홍 길동 3324    5/11/96 50354
      임 꺽정 5246    15/9/66 287650
      이 성계 87654    6/20/58 60000
      정 약용 908683    9/40/48 365000
  • awk '{print $1}' awkfile

    • 구분자를 사용해(default ' ') 첫번째 print

      홍
      임
      이
      정
  • awk '{print NR}' awkfile

    • 파일의 레코드 번호 출력

      1
      2
      3
      4
  • awk '/길동/' awkfile

    • 길동을 찾아서 출력

      홍 길동 3324    5/11/96 50354
  • awk '/정/{print "\t안녕하세요? " $1, $2 "님!"}' awkfile
    • 정이 들어가는 데이터를 찾고, 텍스트를 붙여서 새로운 결과 출력
    안녕하세요? 임 꺽정님!
    안녕하세요? 정 약용님!
  • awk '/^정/{print $1, $2, $3}' awkfile

    • 맨 앞에 정이 들어가는 데이터를 찾고, 출력

      정 약용 908683
  • df | awk '$4 < 100000' : |을 이용해 파이프라인 생성

      devfs                388       388         0   100%     672                   0  100%   /dev
      map -hosts             0         0         0   100%       0                   0  100%   /net
  • awk '{max=($3 > $5) ? $1 : $2; print max}' awkfile

    • 표현식을 검사하기 위해 ?와 :를 사용. if/else가 하는 역할과 같은 결과를 의미
    • $3과 $5를 비교해서 $3이 크면 $1을 출력하고, 아니면 $2를 출력해라

      길동
      꺽정
      이
      정
  • awk 'BEGIN {FS=" "} {print $3, $4}' awkfile
    • test.txt 파일의 필드 구분자를 "" 으로 지정하고, 3번째와 4번째 필드를 프린트

  • awk -F ' ' '{print $4}' awkfile

    • ' '로 split하고 4번째 값 출력

      5/11/96
      15/9/66
      6/20/58
      9/40/48
  • 더 자세한건 제 블로그 참고

  • sed
    • sed 's/찾을 텍스트/바꿀 텍스트/g' 파일명으로 사용함
      • -i 옵션은 --in-place를 의미함
      • s는 문자열 치환을 의미
      • g는 모든 라인에 적용한다는 의미. 작성하지 않으면
    • sed 's/root/ROOT/g' /etc/group | grep ROOT
    • sed 's/root/ROOT/g' /etc/group | grep root
    • sed -n '3,7p' /etc/group
  • alias : 별칭
    • alas ll = 'ls -al'
  • xargs
    • 주로 find, ls, cat 뒤에 파이프로 사용됨
    • 앞 명령어의 결과를 다음 명령어의 입력으로 넘기는 파이프와 함께 사용해, 앞 명령어의 출력값을 다음 명령어의 인자로 넘긴다
    • find를 이용해 mtime이 30일 이상된 파일을 .bak으로 바꾸기
      find . -mtime +30 | xargs mv -i {} {}.bak
  • xargs

    • *.mp3 지우기
    • (Tip) 그러나 찾고 삭제는 find -delete가 좋음. 아래 예제처럼 하면 파일 하나당 서브 프로세스가 생성됨

      find . -name '*.mp3' | xargs rm
  • xargs

    • ls를 이용해 text 파일 목록을 가져오고 각 파일 내용을 cat으로 읽고 병합 파일 만듬

      ls *.txt | xargs cat >> abc.merge
  • xargs
    • find ~/ -type f | grep -H "*.txt$" | xargs grep -H "abcd"
    • 디렉토리에서 txt파일을 우선 찾은 다음 이름에 abcd를 포함하는 파일을 또 찾음

Nohup & Screen

  • 무언가 작업을 백그라운드(내 터미널을 꺼도 작업이 돌아가도록)에서 돌고 싶은 경우
    • 대표적으로 nohup, screen 등을 사용함
  • nohup

    • 리눅스에서 쉘 스크립트 파일이나 파이썬 파일을 데몬 형태로 실행시킴
    • 터미널 세션이 끊겨도 실행을 멈추지 않고 동작함
    • &을 사용 => 프로세스 실행할 때 백그라운드 동작하도록 만듬
    • nohup으로 실행할 쉘 스크립트 파일은 퍼미션이 755 이상이어야 함
  • 사용 방법

      nohup shell.sh &
  • nohup

    • 종료하는 두가지 방법

      ps ef | grep shell.sh
      ps -ef로 pid 번호 찾은 후
      kill -9 pid번호
  • 로그

    • nohup을 만들면 nohup.out 파일이 생성됨
  • screen

    • nohup을 대체할 수 있음

      apt-get install screen
    • 스크린 생성

      screen -S screen_name
    • 저는 screen -dmS screen_name을 자주 사용함

      • -dm : 커맨드를 실행하고 대화식으로 하지 않고 인자로 연결
      • -S : 사용 가능한 이름을 지정해 나중에 쉽게 다시 연결
  • screen

    • 스크린으로 진입

      screen -r screen_name
    • 스크린 리스트 확인

      screen -list
  • scp
    • Secure Copy(remote file copy program)의 줄임말
    • Secure Shell(ssh)을 이용해 네트워크로 연결된 호스트간에 파일을 주고 받는 명령어
    • -r : 재귀적으로 폴더 복사
    • -P : ssh 포트 지정
    • -i : ssh identify file을 지정해 파일 이동
  • local -> remote

      scp local_path user@ip:remote_directory
  • scp

    • remote -> local

      scp user@ip:remote_directory local_path
    • remote -> remote

      scp user1@ip1:source_remote_directory user2@ip2:target_remote_directory
  • /dev/null

    • 리눅스 null
    • null, 블랙홀 같은 공간이라 생각
    • 출력 스트림을 버릴 경우 사용됨

      echo "hello"
      # hello
      echo hello > /dev/null
      # 아무것도 출력되지 않음
  • /dev/null

    • 주로 2>&1 이런 것들과 같이 쓰임
    • 2(표준 에러)를 1(표준 출력)으로 바꿔서 redirect!
    • & : 백그라운드에서 실행하라

      rm test > /dev/null 2>&1
  • 유용한 팁 : 터미널에 출력되는 값 복사할때 어떻게 하나요, 현재 경로 같은 것들

    • pbcopy : 명령어의 결과를 클립보드로 복사

      echo "hihi" | pbcopy
    • jupyter 경로를 복사하고 싶은 경우

      echo `which jupyter` | pbcopy
  • 현재 경로 복사하고 싶은 경우

      echo `pwd` | pbcopy

쉘 스크립트

  • 쉐뱅(Shebang)

    • 쉐뱅, 셔뱅..?
    • #! 이 친구를 뜻함

      • 이 스크립트를 bash 쉘로 명령어를 해석하겠다. 인터프리터 지정 명령어
      • 만약 사용하는 OS에 bash가 없을수도 있음
      #!/bin/bash
    • 사용할 수 있는 쉘 확인하는 방법

      cat /etc/shells
  • 쉘 스크립트 만들기

    • 우린 이미 했음
    • vi hello.sh

      #!/bin/bash
      echo "Coool!"
      echo "Hello!"
  • 하지만 vs code에서 그냥 file_name.sh를 만들면!

  • 주석

    • #로 시작하면 주석
  • vi하고 Insert 모두에서 한줄 삭제하기 : dd
  • 함수

    • 다른 언어와 차이 없음
    • function은 작성해도 되고, 생략해도 됨

      #!/bin/bash
      
      hello_function() {
        echo "Hello!!!"
      }
      
      function hello_function2() {
        echo "Hello2~"
        echo "인자값: ${@}"$
      
      hello_function
      hello_function2
      
      hell_function2 "hi" "hello"
  • 변수
    • 변수 사용시 = 기호 앞뒤로 공백없이 사용
    • 파이썬 습관이 익숙해서 띄어쓰기를 하시면 에러 발생합니다 ㅠ(띄어쓰기에 민감)
    • 함수 안에서 사용하는 변수는 local, 그 밖에 있으면 global variable
    • 변수 사용은 ${변수} 이렇게 쓰자!
  • 위치 매개 변수
    • \$0 : 실행된 스크립트 이름
    • \$1 : 인자 순서대로 부여 10번째 부턴 "{}" 감싸줘야 함
    • \$@ : 전체 인자값
    • \$# : 매개변수 총 개수
    • \$? : 실행 명령의 exit code(성공한 경우 0, 더 궁금하면 bash exit code 검색)
  • 위치 매개 변수

    • test.sh

      #!/bin/bash
      
      echo "file name is"  $0
      echo "first arg is" $1
      echo "second arg is" $2  
      echo "all arg: " $@
      echo "len of arg : " $#
  • 실행하기

      bash test.sh 1 2 3
  • for loop

    • for ~ in 하고 do / done
    • for_loop.sh

      #!/bin/bash
      SEQUENCE=$(seq 0 9)
      for i in $SEQUENCE
      do
        echo "Running loop seq ${i}" 
      done
  • for loop

    • seq를 안쓰고 수동으로 입력하기
    • for_loop2.sh

      #!/bin/bash
      ORDER="5 6 7 8 9 4 3 2 1 0"
      for i in $ORDER
      do
        echo "Running loop ${i}" 
      done
  • for loop

    • 0부터 1씩 증가하는 for loop(C/C++ 스타일)
    • for_loop3.sh

      #!/bin/bash
      for ((i=0;i<=9;i++))
      do
        echo "Running loop "$i
      done
  • while

    • while [condition]; do
    • 조건이 true일 때 실행
    • 실행 횟수 지정이 필요하지 않는 반복문이 필요할 때 좋음
    • 비교 표현식 줄임말
      • eq - equal(=)
      • ne - not eqaul(<>)
      • lt - little(<)
      • le - little or equal (<=)
      • gt - greater(>)
      • ge - greater or eqaul(>=)
    • while_loop.sh

      #!/bin/bash
      
      count=0
      while [ ${count} -le 5 ]; do
        echo ${count}
        count=$(( ${count}+1 ))
      done
  • 조건문(if elif)
    • if [ condition ]; then ~ fi로 구성됨(fi는 if를 거꾸로)
    • if_test.sh
    • AND 조건 : &&
    • OR 조건 : ||
  • if_test.sh
```
#!/bin/bash
string1=$1
string2=$2
string3="awesome"

if [ ${string1} == ${string2} ]; then
    echo "string 1, string2 is same"
elif [ ${string1} == ${string3} ]; then
    echo "string 1 is awesome"
else
    echo "else condition"
fi
```
  • 선택문(case문)
    • 정규식을 지원함
    • | 기호로 다중값 입력 가능(or 조건), 조건 문장 끝에 ;;로 끝을 표시함
    • case ~ esac(easc는 case 거꾸로)
  • case_test.sh

      #!/bin/bash
    
      for string in "hi" "HELLO" "WORLD" "hello" "world" "wow" "awesome" "start" "end" "etc"; do
          case ${string} in
              hello|HELLO)
                  echo "hello or HELLO : ${string}"
                  ;;
              wo*)
                  echo "wo로 시작하는 단어 : ${string}"
                  ;;
              a*|end)
                  echo "a로 시작하는 단어 or end일 때 : ${string}"
                  ;;
              *)
                  echo "기타 : ${string}"
                  ;;
          esac
      done
  • set
    • 옵션 또는 매개변수 지정
    • 안정적인 스크립트를 위해 아래 옵션은 default로 해두면 좋음
    • set -e : 오류가 발생하면 스크립트를 바로 종료. 파이썬에서 오류나면 그 밑에 실행안되는 것을 해주는 옵션. 이 옵션을 안주면 차례대로 주루룩 내려감
    • set -u : 정의하지 않은 변수가 있으면 바로 종료
    • set -o pipefail : 파이프라인의 명령이 실패하면 해당 리턴 코드가 파이프라인의 리턴 코드로 사용됨
  • set_test.sh

      #!/bin/bash
    
      set -euo pipefail
      echo "hi"
    
      echi hihihi
      # error 발생
    
      echo "hello"
  • Bash에서 ''와 ""는 다릅니다!!!!!

    • 파이썬에 익숙한 우리가 자주 일으키는 실수
    • ''(작은 따옴표)는 단순히 문자열을 의미하고, ""(쌍 따옴표)는 변수의 값이 참조됨

      #!/bin/bash
      BASH_VAR="Bash Script is Amazing"
      
      # single quote
      echo '${BASH_VAR}'
      
      # double quotes
      echo "${BASH_VAR}"
      ${BASH_VAR}
      Bash Script is Amazing
  • trap
    • 스크립트 또는 쉘이 언터럽트를 가로채서 스크립트 내에서 어떤 작업을 할 수 있도록 하는 기능을 제공
```
#!/bin/bash

set -euo pipefail
# 종료가 되거나 끝나면 메세지 전송
trap '[ "$?" -eq 0 ] || send_error ${LINENO} ${FUNCNAME}' EXIT

function send_error {
  local lineno=$1
  local funname=$2
  local current_date=$(date '+%Y-%m-%d %H:%M:%S')
  curl 'https://hooks.slack.com/services/T00000000/BXXXXX/asdasdasd' -d "payload={\"text\": \"[CRON][ERROR] LineNum=${lineno} FunName=${funname}\"}"
}

function slack_test {
   echo "now sleep..."
   echo "command + c"
   sleep 5
}
```

정리

  • 쉘 스크립트, 익숙하지 않아 매우 어렵죠?
    • 3시간 동안 정말 많은 것들을 들었는데, 아마 점점 서버를 직접 만지다보면 쉘 커맨드나 쉘 스크립트에 대한 필요성을 느낄거임
    • 지금 키워드 정도로 일단 인지해두고, 나중에 하나씩 다시 공부하는 방법도 추천
  • Docker 같은 친구를 잘 하려면 쉘 스크립트를 어느정도 할 수 있어야 좋음
  • 어렵지만 제가 알려드린 내용 위주로 일단 복습은 꼭!
  • (피와 되고 살이 됨.. 어디서 잘 안 알려줘요. 저도 혼자 책보고 공부함)

다음 수업

  • 5회차(20/1/31)
    • 클라우드란 무엇일까? 클라우드의 핵심
    • 데이터 엔지니어링이란 무엇일까? 데이터 엔지니어링 퀵 요약
  • 6회차(20/2/14)
    • Airflow를 사용한 간단한 ETL 파이프라인 만들기
  • 7회차(20/2/28)
    • 각종 개발 도구들(IDE, Editor)
    • MLOps 개론
  • 8회차(20/3/13)
    • MLOps 중 실험 플랫폼
  • 9회차(20/3/27)
    • Git, Github
  • 10회차(20/4/10)
    • Docker
  • 11회차(20/4/24)
    • Test Code
  • 12회차(20/5/8)
    • Dashboard