레이블이 ssh인 게시물을 표시합니다. 모든 게시물 표시
레이블이 ssh인 게시물을 표시합니다. 모든 게시물 표시

ssh 로그인 후 바로 종료 문제

# k8s pod 내에 sshd -D 를 기동 후
# 다음과 같이 ssh 연결을 하면 바로 연결이 close 된다.
ssh root@localhost -vvv

... 생략 ...
Last login: Sat Apr 29 07:38:26 2023 from 127.0.0.1
debug3: receive packet: type 96
debug2: channel 0: rcvd eof
... 생략 ...
Connection to localhost closed.
debug1: Exit status 255

# receive packet : type 96(SSH_MSG_CHANNEL_EOF)으로
# 보통 연결된 ssh 에서 exit/logout 하면 받는 패킷이다.

# lastlog(/var/log/lastlog) 로 마지막 로그를 봐도 로그인 된 흔적이 있다.
Username         Port     From             Latest
root             pts/3    127.0.0.1        Sat Apr 29 07:38:28 +0000 2023
... 생략 ...

# lastb(/var/log/btmp)로 실패한 로그인 기록은 보면 없다고 나오고
# last(/var/log/wtmp) | head -2 로 성공한 로그인 기록을 보면 내역에도 기록 되어 있다.
# 그런데 로그인 후 바로 로그아웃되었다.
root     pts/3        127.0.0.1        Sat Apr 29 07:38 - 07:38  (00:00)
root     pts/3        127.0.0.1        Sat Apr 29 07:38 - 07:38  (00:00)

# 혹시 root 기본 쉘을 확인해보면 bash 정상
cat /etc/passwd | grep groot
root:x:0:0:root:/root:/bin/bash

# ssh closed 시 verbose 내용에 255 종료상태가 있는것을 보고 
# 체크1
# 로그인시 ~/.profile, ~/.bashrc 를 rename 으로 로딩을 하지 않아도 closed 된다.

# 체크2
# root/.ssh/ 에 있는 environment 파일이 다른 정상 container 와 달리 꽤 커서 살펴봤다.
# pod(container)의 파일을 로컬로 복사
kubectl cp {namespace}/{pod_name_ssh_접속정상}:/root/.ssh/environment ./environment1
kubectl cp {namespace}/{pod_name_ssh_접속문제}:/root/.ssh/environment ./environment2

# environment1 파일은 500라인인데, environment2 파일은 1000라인이다.
# 문제가 있는 container /root/.ssh/environment 의 내용을 라인을 지워가면서 접속 여부를 확인해봤다.
# 확인결과 environment 내용에 상관없이 라인수를 991로 줄이면 접속이 성공한다.
# 접속시 너무 많은 environment 설정(현재 client 와 중복도 많이 되고 있었음) 문제였음...

ssh - alacritty unknown terminal type

# alacritty 터미널 에뮬레이터 사용중 원격 서버에 ssh 접속 했는데,
# clear 명령 실행시 다음과 메시지가 나오면서 화면이 지워지지 않는다.
'alacritty': unknown terminal type.

# 다음과 같이 ssh alias 로 TERM 변수를 설정해 접속하면 된다.
alias ssh='TERM=xterm-256color ssh'
ssh ysoftman@ysoftman.hostname.blabla

aws bastion 접속없이 로컬에서 kubectl 사용하기

# 보안상의 이유로 다음과 같이 aws bastion 을 사용한다.
# aws private <-> aws bastion <-> 외부(local...)
# 그래서 기본적으로는 다음과 같이 aws eks 클러스터에 kubectl 명령은 bastion 에 접속 후 사용해야 한다.
ssh -i aws-ysoftman.pem ec2-user@xxxx.ap-northeast-2.compute.amazonaws.com
[ec2-user@ip-xxxxxx ~]$ kubectl get ns

# ssh tunneling 으로 로컬에서 bastion 통해 바로 kubectl 을 사용(연결)할 수 있다.
# -f 백그라운드 실행, 추후 필요없으면 ssh 프로세스 kill 필요, -f 없이 사용해도 되고,이러면 ctrl+c 로 종료
# -N 원격 명령을 실행하지 않는다. 포트 포워딩할때 같이 사용
# -L 로컬포트->특정호스트:포트로 바인딩
# alias 로 만들어 사용하자.
alias aws-prod-start-tunnel='ssh -fNL 29443:xxx.ap-northeast-2.eks.amazonaws.com:443 -i ~/.ssh/aws-ysoftman.pem ec2-user@xxx.ap-northeast-2.compute.amazonaws.com'
alias aws-prod-stop-tunnel="ps -ef | grep 'ssh -fNL' | grep -v grep | awk '{print \$2}' | xargs kill -9"


# 로컬 호스트에 도메인 추가한다.
sudo vi /etc/hosts
127.0.0.1     kubernetes.default

# 참고로 k8s 허용하지 않는 도메인을 사용하면 다음과 같은 에러가 발생한다.
Unable to connect to the server: x509: certificate is valid for xxx.ap-northeast-2.eks.amazonaws.com, xxx.ap-northeast-2.compute.internal, kubernetes, kubernetes.default, kubernetes.default.svc, kubernetes.default.svc.cluster.local, not aws-ysoftman

# 이 에러를 무시하려면 다음과 같이 매번 옵션을 명시해 실행할 순 있다.
# kubectl get ns --insecure-skip-tls-verify

# aws cli 로 kubectl 접속 설정 파일을 생성한다.
aws eks update-kubeconfig --region ap-northeast-2 --name ysoftman-k8s --kubeconfig ~/.kube/kubeconfig-aws-ysoftman.yaml

# 접속 설정 파일 중 server 부분을 다음과 같이 변경한다.
vi ~/.kube/kubeconfig-aws-ysoftman.yaml
apiVersion: v1
clusters:
  - cluster:
      server: https://kubernetes.default:29443

# 이제 (ssh 연결된 상태니) 로컬에서 kubectl 응답을 받을 수 있다.
kubectl get ns

ansible ssh password 옵션

# ansible 수행시 target 서버에 커버로스 인증을 사용할 수 없어
# 직접 ssh password(암호)를 명시해야 되는 경우 --ask-pass 옵션을 사용하면
# 암호 입력 프롬프트가 표시해 암호를 입력 할 수 있다.
ansible-playbook -i testserver test.yaml --ask-pass

# 또는 인벤토리 파일에 ansible_password 변수로도 설정할 수 있다.
testserver ansible_host=ysoftman.test.com ansible_password="password123"

# 그런데 위 두방법 모두 다음과 같은 에러가 발생한다.
to use the 'ssh' connection type with passwords, you must install the sshpass program

# ansible 은 ssh 연결로 암호를 묻는 프롬프트가 뜨는데
# sshpass 는 암호 프롬프트 없이 인증 해준다.

# sshpass 설치
# centos 계열
yum install sshpass

# ubuntu 계열
apt-get install sshpass

# mac
brew install hudochenkov/sshpass/sshpass

# 이제 --ask-pass 사용시 최초 한번만 암호를 입력하면 에러 없이 진행된다.
ansible-playbook -i testserver test.yaml --ask-pass
# 또는 암호 프롬프트 없이 사용할 경우
sshpass -p password123 ansible-playbook -i testserver test.yaml --ask-pass

# 참고로 ssh 연결시에 암호 프롬프트 없이 사용하기
sshpass -p password123 ssh ysoftman@ysoftman.test.com

ansible 속도 개선

# ansible 은 기본적으로 대상 서버에 task 수행에 필요한 모듈을 복사 후
# task 를 실행하는데 이 모듈 복사 과정으로 task 수행이 느리다.
# 그런데 이 복사 ssh operation 횟수를 pipelining 으로 줄여 속도를 높일 수 있다.
https://docs.ansible.com/ansible/2.4/intro_configuration.html#pipelining

# 단 sudo 명령을 쓰는 경우 대상 호스트의 /etc/sudoers 권한작업이 필요하다.
# 다음과 같이 pipelining 활성화
# vi ansible.cfg
[ssh_connection]
pipelining = true

# 테스트 결과 수행 속도가 1/2 로 줄어 들었다.
pipelining = fasle : 5min
pipelining = true : 2min 30s

# 참고로
# ansible 1.3 ~ 1.5 에서는 accelerate_port 를 사용했었고
# ansible 1.5 이후 pipelining 추로 accelerate_port 는 설정할 필요가 없어졌다.

jenkins 동시 수행되는 job들 중 ssh 연결 실패

jenkins 동시 수행되는 job들 중 ssh 연결 실패(UNREACHABLE 에러)가 발생하는 경우가 있다.
jenkins 에 5개의 잡이 다음과 같은 주기로 실행되고 있다.
a job : 1분 주기
b job : 2분 주기
c job : 2분 주기
d job : 5분 주기
e job : 5분 주기
각 잡들은 ansible 로 모두 같은 파일 서버로 부터 각 잡에 맞는 파일을 다운로드 한다.
간헐적으로 잡들의 ansible 연결 실패 발생한다.
다음과 같은 증상들이 있다.
- 간헐적으로 ssh 연결 실패가 발생한다.
- 연결 실패가 발생하면 최소 2개의 잡이 동시에 발생한다.
- ansible -vvv 옵션으로 자세한 verbose 를 찍어보면, 다음 처럼 특정 controlpath(cp, 소켓파일)을 사용한다.
 예) 8a8131ca11
 ssh -o ControlPath=/home/ysoftman/.ansible/cp/8a8131ca11
- 간헐적 에러가 발생하는 시간은 8a8131ca11 가 생성되는 시간이다.
- 최초 8a8131ca11 생성 후 ansible ssh 연결이 잘 되다가 갑자기 끊어지는 현상이 있다.
- ssh -o ControlPersist=60s (ansible ssh 디폴트, https://docs.ansible.com/ansible/latest/plugins/connection/ssh.html) 옵션을 사용해 8a8131ca11 가 60초만 유지후 삭제 될거라고 생각했지만 60초 후에도 계속 유지되는것처럼 보였다.
우선 모든 잡들이 8a8131ca11 이름을 사용하고 있다.
ansible.cfg 에 ssh 관련 별다른 옵션은 설정하지 않았다.
따라서 ansible 의 기본 controlpath 생성 로직을 사용하게 된다.
https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection/ssh.py -> _create_control_path()
create_control_path() 는
remote host, remote port, remote user, connection, pid 로
sha1() -> hdex -> digest로 앞 10바이트만 잘라서 cp 이름을 정한다.
하지만 아래 소스를 보면 control_path 없으면, host, port, user만 사용된다.
결국 같은 host, port, user 를 사용하는 5개의 잡은 모두 같은 cp 이름을 생성한다.
https://github.com/ansible/ansible/blob/47aea84924e8149e153107564c8b029dc4f52c27/lib/ansible/plugins/connection/ssh.py#L663
if not self.control_path:
    self.control_path = self._create_control_path(
        self.host,
        self.port,
        self.user
    )
8a8131ca11(cp 파일) 60초 후 삭제될거라 생각했지만
1분 간격으로 실행되는 a잡이 실행시 ssh -o ControlPersist=60s 로
cp 60s 늘리거나 새로 생성 한다.
이런식으로 cp 파일은 의도하지 않게 몇일 동안 삭제 되지 않다가 잡(ansible) 수행시
어떤 이유에서인지 간헐적으로 cp 파일 삭제 후 생성되는 순간이 발생하고
이때 삭제된 cp 를 사용하려는 ansible 잡이 연결 실패 에러가 나는것으로 보인다.

# 해결
# ansible 파일 서버 inventory 파일에
# ansible_ssh_common_args 옵션을 사용하면
ysoftman.fileserver  ansible_ssh_common_args="-o ControlPersist=10s"

# 다음과 같이 명령 뒤에 설정값을 중복으로 붙게 되는데
# ssh 는 먼저 선언한 값으로 처리해 10s 값이 적용되지 않는다.
ssh -o ControlPersist=60s -o ControlPersist=10s

# 그래서 별도의 ansible_ysoftman.cfg 파일을 만들어 설정했다.
[defaults]
host_key_checking = False
remote_user = ysoftman
transport = ssh
stdout_callback = debug

[ssh_connection]
# UNREACHABLE 에러 발생시 발생시 2번은 재시도
retries = 2

# ssh -tt(tty 강제 할당) 옵션 비활성화
usetty = no

# ssh 옵션 자세한 설명은 man ssh_config 참고
# ControlMaster=auto 사용할 수 있는 cp 파일이 있으면 사용하고 없으면 새로 만든다.
# ControlPersist=yes(또는 0) cp 파일이 백그라운드로 계속 남아 있도록 한다.
# ssh_args = -o ControlMaster=auto -o ControlPersist=yes

# ansible 실행시 ANSIBLE_CONFIG 환경변수로 적용
ANSIBLE_CONFIG=ansible_ysoftman.cfg ansible-playbook -i ./inventory/aaa do_something.yml

# 참고
# ssh cp 관련 control command
# 8a8131ca11 종료
ssh -o ControlPath=/home/ysoftman/.ansible/cp/8a8131ca11 -O exit ysoftman@10.10.10.10

# 8a8131ca11 상태 확인
ssh -o ControlPath=/home/ysoftman/.ansible/cp/8a8131ca11 -O check ysoftman@10.10.10.10

ssh접속 에러 too long for Unix domain socket

# ssh 접속시 다음과 같은 에러가 발생한다.
too long for Unix domain socket

# ssh config 설정에서 다음을 주석 처리하자.
# vi ~/.ssh/config
# ControlPath ~/.ssh/sockets/%r@%h-%p
# ssh argument token 설명
# %r : 원격 사용자 이름
# %h : 원격 홈디렉토리
# %p : 원격 포트
# %u : 로컬 사용자 이름
# %d : 로컬 홈디렉토리
# %L : 로컬 호스트네임
# %l : 로컬 도메인을 포함한 호스트네임
# 자세한 내용은 https://man.openbsd.org/ssh_config#TOKENS

ansible Shared connection closed

# 주기적으로 ansible 을 실행하다 보면 다음과 같이 ssh 커넥션 에러가 발생할때가 있다.
# ansible 2.7.2

TASK [Gathering Facts] *********************************************************
fatal: [서버]: UNREACHABLE! => {
    "changed": false,
    "unreachable": true
}
MSG:
Failed to connect to the host via ssh: Shared connection to 서버 closed.

# 이와 같은 ansible issue 가 등록돼 있다.
https://github.com/ansible/ansible/issues/26359

# 뚜렷한 해결책은 없고 controlpersist timeout 을 늘리라 고만 한다.ㅠ
# ansible.cfg 에 ssh 옵션(man ssh_config 참고)
# TCP 커넥션 하나에 여러개의 ssh 커낵션 허용(multiplexing)을 여부
# yes: controlpath 로 설정된 소켓으로 연결을 기다린다. 이 소켓에 세션이 추가 될 수 있다.
# no: 새 소켓을 만들지 않고 controlpath 에 있다면 세션 추가해서 사용한다.
# auto: controlpath 소켓이 있으면 사용하고, 없으면 새 소켓을 만든다.
# ControlMaster=auto
# ssh 커넥션 유지 시간, 기본 단위는 초다.
# m,s: x분,x초 만큼 커넥션 유지
# no: 클라이언트 커넥션 종료되면 바로 종료
# yes or 0: 커넥션 indefinitely(무한정) 유지
# ControlPersist=30m
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=30m

# ssh 실패시 자세한 로그를 보기 위해 ansible -vvv 옵션을 주고 보면
# 에러 직전까지 여러번의 ssh 연결을 수행을 성공한다.
# 하지만 에러 직전의 ssh 커맨드가 실패하고 명령 옵션을 보면 다음과 같다.
ssh -C \
-o ControlMaster=auto \
-o ControlPersist=60s \
-o StrictHostKeyChecking=no \
-o KbdInteractiveAuthentication=no \
-o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey \
-o PasswordAuthentication=no \
-o User=ysoftman \
-o ConnectTimeout=10 \
-o ControlPath=/ysoftman/.ansible/cp/8a8131ca11
-tt ysoftman_server
'/bin/sh -c '"'"'/usr/bin/python /ysoftman/.ansible/tmp/ansible-tmp-1570416122.87-200449718228174/AnsiballZ_command.py && sleep

# 위를 실행하면 문제가 되는 에러가 발생한다.
Shared connection to ysoftman_server closed.

# 성공,실패의 차이를 보면 성공의 경우 -tt 옵션이 없었고,
# 실패의 경우에서 -tt 옵션을 빼고 실행하면 잘된다.
# 찾아보니 -t 옵션은 ssh 연결시 화면을 보기 위해 tty 를 할당한다.
# -tt 로 t 를 여러번 주면 강제 할당하게 된다.
# 참고로 -T 옵션으로 -tt 를 disable 할 수 있다.

# ansible.cfg 에 다음 옵션을 주면
# ssh -tt(tty 강제 할당) 옵션 비활성화한다.
[ssh_connection]
usetty = no

# 참고
https://linux.die.net/man/1/ssh
https://docs.ansible.com/ansible/latest/plugins/connection/ssh.html

vscode 원격 개발

# vscode 1.35 부터 remote develop extension 을 설치해
# ssh, docker container, wsl 의 원격 개발 환경을 이용 할 수 있다.
# 참고로 아이콘도 좀 심플하게(예쁘게) 변경됐다.~ㅎ

# 원격 접속은 원격 서버의 ${HOME}/.vscode-server 프로그램을 설치하고 vscode-server 가 실행돼 원격으로 접속하게 된다.
# vscode-server 는 wget 로 다운로드를 하게 되는데
# 참고로 사내망이라면 http_proxy 환경 변수를 설정 해줘야 한다.

# docker container 가 이미 떠있는 경우
remote-containers : attach to running container
-> 현재 떠있는 컨테이너 선택 -> 새 vscode 창이 오픈

# 새 vscode 가 생성되면 컨테이너의 소스 파일을 열어 볼 수 있고,
# vscode 터미널에서 빌드 커맨드 등을 실행할 수 있는 상태가 된다.

# remote ssh 는 ~/.ssh/config 와 ~/.ssh/authorized_keys 사용한다.
# kerberos 인증 환경에서도 접속할 수 있다.
# settings.json 설정에 다음을 추가하면 로그인 터미널 상태를 표시해준다.
"remote.SSH.showLoginTerminal": true

# 로그인 터미널에 다음과 같은 에러가 발생하는 경우
channel 2: open failed: administratively prohibited: open failed

# 대상 호스트 서버의 /etc/ssh/sshd_config 에 tcp 포워딩 가능하도록 설정한다.
AllowTcpForwarding yes

# 그리고 sshd 서버를 재시작한다.
sudo systemctl restart sshd

# 기타 접속 이슈 해결방법 참고
https://code.visualstudio.com/docs/remote/troubleshooting#_troubleshooting-hanging-or-failing-connections

# remote develop 기능은 vscode live share(로컬 코드를 공유)와 비슷하지만
# 원격 장비의 코드를 vscode 로 볼 수 있어 좋은것 같다.

docker sshd 설정

# redhat 계열(centos) 리눅스에서 서비스 관리 프로그램 변화
# centos6  RHEL(RedHat Enterprise Linux)6
서비스 시작,중지 : service 서비스명 start|stop|restart|status
부팅시 서비스 등록 : chkconfig 서비스명 on|off
서비스 상태 확인 : chkconfig --list

# centos7, RHEL(RedHat Enterprise Linux)7
서비스 시작,중지 : systemctl start|stop|restart|status 서비스명
부팅시 서비스 등록 : systemctl enable|disable 서비스명
서비스 상태 확인 : systemctl list-unit-files

# 그리고 systemctl 은 systemd 데몬이 실행되고 있어야 한다.
예전 service 의 SysV(system5)의 init 스크립트를 systemd 로 대체하고 있다.
/usr/sbin/init -> ../lib/systemd/systemd

#####

# systemctl 실행시 systemd 가 실행중이지 않다면 아래 에러가 발생한다.
Failed to get D-Bus connection: Operation not permitted

# systemd 실행을 위해서
# (--privileged 옵션을 사용하지 않는다면) --tmpfs 옵션으로 컨테이너의 /tmp /run 를 tmpfs 로 마운트해야 한다.
# /sys/fs/cgroup 가 read only로 마운트돼있어야 한다.
# 호스트에 /sys/fs/cgroup 가 존재하지 않아도 된다.
# /sbin/init 가 PID 1 로 실행되도록 한다.
docker run --name centos7 --hostname centos7 -p 9022:22 --user root --tmpfs /run --tmpfs /tmp -v /sys/fs/cgroup:/sys/fs/cgroup:ro -d centos:7 /sbin/init

# 현재 도커 이미지 root 가 아니면 다음처럼 권한 에러가 발생한다.
# 이 경우 docker run 시 --user root 를 사용해야 한다.
docker logs -f centos7
Failed to create root cgroup hierarchy: Permission denied

# 컨터네이너 접속해서 systemd 확인
docker exec -it centos7 /bin/bash
ps -ef | grep systemd

# 컨테이너 삭제
docker rm -f centos7

# 참고
https://developers.redhat.com/blog/2016/09/13/running-systemd-in-a-non-privileged-container

#####

# docker sshd 를 사용하지 말도록 권하고 있다.
# https://jpetazzo.github.io/2014/06/23/docker-ssh-considered-evil
# 서비스가 아닌 개인 테스트 용도로 sshd 를 적용해 보자.
# sshd 설치
yum install -y openssh-server
# sshd 구동 및 상태 확인
systemctl start sshd && systemctl status sshd

# ysoftman 사용자 추가
useradd ysoftman

# ysoftman password 설정
passwd ysoftman

# 호스트에서 접속해보자
# 위에서 컨테이너 실행시 9022 -> 22(sshd) 로 바인딩해뒀다.
ssh ysoftman@localhost -p 9022

docker container lines cols 초기값 변경

# 도커 컨테이너에 접속해서 처음 긴명령을 타이핑하거나 vim 을 실행 했을때
# 폭24, 라인80 위치를 넘어가서 덮어 씌워지는 현상이 있다.
# 터미널 크기를 조정하면 그때부터 실제 터미널 폭,라인 크기가 제대로 반영된다.
# 아래 화면을 보면 vim 크기가 터미널 보다 작게 설정된 것을 볼 수 있다.

# 도커 컨테이너를 띄우고 접속을 하면 터미널의 크기가 80x24 로 되어 있다.
# tput 으로 컨테이너의 라인,컬럼을 확인해보자
docker exec -it ysoftman_container tput lines
docker exec -it ysoftman_container tput cols

# 호스트의 실제 터미널의 창 크기($COLUMNS, $LINES) 값을 컨테이너 접속시 전달한다.
docker exec -u ysoftman -e COLUMNS=$COLUMNS -e LINES=$LINES -it ysoftman_centos /bin/bash

# .sh 로 실행해야 할 경우 $COLUMSN, $LINES 는 사용할 수 없어 tput 을 사용한다.
docker exec -u ysoftman -e COLUMNS=$(tput cols) -e LINES=$(tput lines) -it ysoftman_centos /bin/bash

# 관련 이슈 내용 참고

# 참고로 ssh 프로토콜에는 클라이언트의 터미널 크기가 변경될때 크기 다음과 같은 정보를 보낸다.
byte      SSH_MSG_CHANNEL_REQUEST
uint32    recipient channel
string    "window-change"
boolean   FALSE
uint32    terminal width, columns
uint32    terminal height, rows
uint32    terminal width, pixels
uint32    terminal height, pixels

ssh 처음 접속시 호스트 체크 안하기

# ssh 로 처음 접속하는 호스트(~/.ssh/known_hosts 에 미등록)는 다음과 같이 물어본다.
The authenticity of host 'xxxxxxx' can't be established.
RSA key fingerprint is xxxxxxx.
Are you sure you want to continue connecting (yes/no)?

# yes 를 입력하여 known_hosts 에 기록되면 다음부터 물어보지 않지만
# 처음 접속하는 수백대의 호스트 접속마다 yes 를 치는건 힘들다.
# 이경우 다음과 같이 ssh 접속시 호스트 체크를 안할 수 있다.
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=1 ysoftman@10.10.10.10

# 수행하면 다음과 같은 경고 문구가 처음 접속시 한번 나오지만 
# ~/.ssh/know_hosts 에 등록되어 이후 접속부터는 표시되지 않는다.
"Warning: Permanently added 'xxxxx' (RSA) to the list of known hosts"

# ansible 사용시
# ansible.cfg 에 다음과 같이 명시하면 호스트 체크를 하지 않는다.
[default]
host_key_checking = false

# 또는 다음과 같이 ssh 에 직접 옵션을 줄 수 도 있다.
[ssh_connection]
ssh_args = '-o StrictHostKeyChecking=no'

ansible "Shared connection to xxx closed"

2개의 jenkins(젠키스) job(잡) 이 스케줄링에 의해 동시 실행될때
"Shared connection to 아이피 closed"

에러를 발생하며 ssh 접속이 되지 않는다.
각각의 젠킨스 잡은 ansible-playbook 을 수행하는데 2개 모두 같은 호스트를 대상으로 하고 있다.
ansible version : 2.2.1.0
user : ysoftman (가정)
jenkins host os : centos 7.2
target host name : ysoftman-file-server (10.10.10.10) (가정)
target host os : centos 7.2

다음과 같은 에러 메시지와 함께 접속 실패가 발생한다.
(ansible-playbook 실행시 -vvvv 옵션)
<10.10.10.10> SSH: EXEC ssh -vvv -o ControlMaster=auto -o ControlPersist=30m -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=ysoftman -o ConnectTimeout=10 -o ControlPath=/ysoftman/.ansible/cp/ansible-ssh-%h-%p-%r -tt 10.10.10.10 '/bin/sh -c '"'"'/usr/bin/python /ysoftman/.ansible/tmp/ansible-tmp-1488621902.23-156878567418929/command.py; rm -rf "/ysoftman/.ansible/tmp/ansible-tmp-1488621902.23-156878567418929/" > /dev/null 2>&1 && sleep 0'"'"''
fatal: [ysoftman-file-server]: UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: OpenSSH_6.6.1, OpenSSL 1.0.1e-fips 11 Feb 2013\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/ssh_config line 56: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug2: mux_client_hello_exchange: master version 4\r\ndebug3: mux_client_forwards: request forwardings: 0 local, 0 remote\r\ndebug3: mux_client_request_session: entering\r\ndebug3: mux_client_request_alive: entering\r\ndebug3: mux_client_request_alive: done pid = 27663\r\ndebug3: mux_client_request_session: session request sent\r\ndebug1: mux_client_request_session: master session id: 4\r\ndebug3: mux_client_read_packet: read header failed: Broken pipe\r\ndebug2: Control master terminated unexpectedly\r\nShared connection to 10.10.10.10 closed.\r\n", 
    "unreachable": true
}

관련해서 구글링을 열심해 해봤는데

에서는 ControlPath 에 명시된 소켓 경로가 너무 길어서 발생한것으로 2.3 에서는 수정되었다고 한다. 그런데 위 트레이스 로그를 보면 경로명이 긴것도 아니고 동시실행될때만 접속실패가 발생하고 각각의 ansible 잡이 독립적으로 수행될때는 접속이 문제가 없어 이 원인은 아닌것으로 생각된다.


에 나와 같은 문제를 제기하고 있었고 다음과 같이 ansible-playbook 실행시 paramiko(파이썬으로 구현한 openssh) connection 를 사용하라고 한다.
ansible-playbook -i ./ysoftman ysoftman.yml -c paramiko -vvvv

또는


와 같이 playbook(.yml) 에 명시할 수 도 있다.
connection: paramiko

또는

http://docs.ansible.com/ansible/intro_configuration.html#transport
와 같이 ansible.cfg 에 명시한다.
(디폴트 smart 로 설정하면 play에  명시된 connection 을 따른다.)
transport = paramiko

문제가 되었던 서버에서는 paramiko 사용으로 해결되었다.
그런데 다른 서버의 콘솔에서 ansible-playbook 명령을 실행하면 접속 인증 실패가 발생한다. -c ssh 나 -c smart 를 옵션을 주어 실행하면 잘된다.

A 장비(젠킨스)에서 ansible 실행시 -c ssh | smart | paramiko 모두 동작
B 장비(로컬)에서 ansible 실행시 -c paramiko 인증 실패

원인은 B 장비의에서 -c paramiko 를 사용할 경우 .ssh/config 설정파일을 사용하지 않고 .ssh/id_rsa (기본 개인키)파일만 바라보고 있어 인증을 할 수 없는 것이다.
id_rsa 파일이 존재하지 않는다면 : No authentication methods available
id_rsa 파일이 존재하지만 대상 호스트에 공개키가 등록되지 않았다면 : Authentication failed
에러가 발생한다.
.ssh/config 에 명시된 private_key 파일을 id_rsa 로 복사하였더니, -c paramiko 로도 실행이 잘 된다.

[참고1]

에 보면 레드햇계열의 버전 6 이하에서는 openssh 버전이 오래된 ControlPersist 같은 ssh 성능 향상 옵션을 사용할 수 없어 ansible 이 ssh 접속에 paramiko 를 강제로 사용했다고 한다.

[참고2]
controlpersist 로 유지되는 커넥션 종료하기
ssh -o ControlPath=/Users/ysoftman/.ansible/cp/ansible-ssh-10.10.10.10-ysoftman -O exit ysoftman@10.10.10.10
또는 소켓 파일을 모두 삭제
rm -rf ~/.ansible/cp/

vagrant up rsync 에러 해결하기

# 윈도우 administrator 계정에서
# vagrant box add centos/7
# vagrant init centos/7
# 설정하여 vagrant up 시 다음과 같은 에러가 발생한다.
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'centos/7' is up to date...
"rsync" could not be found on your PATH. Make sure that rsync
is properly installed on your system and available on the PATH.

# 호스트가 윈도우인데 rsync 를 사용하게 설정되어 있어 발생한것이다.
# 다음 경로의 centos/7 box 의 vagrantfile 에서 type 의 rsync 부분을 삭제하도록 한다.
C:\Users\Administrator\.vagrant.d\boxes\centos-VAGRANTSLASH-7\1611.01\virtualbox\Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.base_mac = "525400225b53"
  config.vm.synced_folder ".", "/vagrant", type: ""
end

# vagrant ssh 수행시 ssh 클라이언트가 없다면
# https://git-scm.com/download/win 에서 git 을 설치해야 한다.
# 설치시 windows command prompt 에서도 ssh 를 사용할 수 있도록 "use git and optional unix tools from the windows command prompt" 를 선택하자.


ssh alias 실행 안되는 문제

# ssh 로 호스트에 명령을 실행할때 alias 로 지정된 키워드가 실행 안되는 경우가 있다.
# 일반 쉘 명령은 실행된다.
ssh ysoftman@ysoftman-centos7 "ls"

# 하지만 호스트에 alias 설정된 키워드 실행시 찾을 수 없다는 에러가 발생한다.
ssh ysoftman@ysoftman-centos7 "myls"
bash: myls: command not found

# 이유는 interactive 로 쉘이 실행되지 않으면 alias 를 쓸수 없는 경우로
# ~/.bashrc 에 다음과 같이 쉘 옵션을 설정해줘야 한다.
shopt -s expand_aliases

# 그리고 스크립트에 alias 가 있을때 . a.sh 실행은 되지만
# expand_aliases 가 없으면 bash a.sh 는 echoysoftman command not found 발생한다.
# 참고로 shopt 는 bash built-in 명령으로 zsh 에서는 사용할 수 없는 명령이다.
# alias script example
shopt -s expand_aliases
alias echoysoftman="echo ysoftman"
echoysoftman

Windows SSHD 서버 만들기

freeSSHd(http://www.freesshd.com/) 를 사용하면 윈도우를 sshd 서버로 만들 수 있다.
freesshd 를 설치 후 실행시키면 시스템 트레이에 아이콘이 생기고 Settings 메뉴를 선택하면 다음과 같은 설정화면이 나타난다.
보안 프로그램이 설치되어 있다면 ssh 기본 포트 22대신 다른 포트를 사용하도록 한다.

Users 메뉴에서 접속할 수 있는 사용자를 추가해 주자.

이제 Server status 에서 SSH 서버를 실행(Click here to start it) 하고 안될 경우 freesshd를 unload 하고 다시 실행시켜 본다.

이제 putty 를 사용하여 ssh 로 접속~

git command

# git 설정 확인
git config --list

# git color ui 설정
git config --global color.ui auto

# true 로 활성화하면 checkout 시에는 CRLF 로 변경되고 commit 시에는 LF 로 변경되어 커밋된다
# false 로 비활성화하면 변환없이 그대로 체크아웃, 커밋된다.
# 디폴트는 fasle 이고
# 윈도우에선 true, 맥과 리눅스에선 false 로 사용한다.
git config --global core.autocrlf  false

# git alias 를 다음과 같은 방식으로 설정 할 수 있다.
git config --global alias.br branch
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.st status

# git diff 등에서의 컬러 사용
git config --global color.ui auto

# git 에디터를 vim 으로 설정(--system 은 전체 사용자, --global 은 현재 사용자)
git config --global core.editor vim

# git 머지툴을 vimdiff 로 설정
git config --global merge.tool vimdiff

# git 사용자 email 과 이름 설정
git config --global user.email "ysoftman@gmail.com"
git config --global user.name "ysoftman"

# 위 config 명령들은 실행후 .gitconfig 에 다음과 같이 alias 가 추가된다.
# .gitconfig 에 직접 추가해도 된다.
git config -e 또는 vi ~/.gitconfig
[color]
    ui = auto
[alias]
    br = branch
    co = checkout
    ci = commit
    st = status
[color]
    ui = auto
[credential]
    helper = cache
[core]
    editor = vim
[merge]
    tool = vimdiff
[user]
    email = ysoftman@gmail.com
    name = ysoftman

# 각 저장소마다 별도의 설정은 .git/config 를 수정한다.
vi .git/config
[user]
    email = ysoftman2@gmail.com
    name = ysoftman2

# 또는 글로벌 옵션 제거하고 설정
git config user.email "ysoftman@gmail.com"
git config user.name "ysoftman"

# git 2.0 이전에서는 push.default 를 설정해야 한다.
# matching : 원격 브랜치와 같은 이름이면 모두 푸시
# simple : 현재 브랜치만 푸시 (git2.0 부터 디폴트)
git config --global push.default simple

# pre-push, pre-commit 등의 hook 파일 경로(디폴트: .git/hooks) 변경
git config core.hooksPath .github

#####

# git 암호 저장
# ~/.git-credentials 파일 생성되며 id,pw 가 저장된다.
# 하지만 암호화 되지 않아 주의해야 한다.
git config --global credential.helper store

# 파일로 저장하지 않고 일정시간(디폴트 15분)동안 id,pw 를 캐싱한다.
git config --global credential.helper cache

# push 할때 현재 저장소 암호변경이 필요한경우
# credential.helper 변수를 제거해 id,pw 를 다시 입력 받도록 한다.
git config --unset credential.helper
git push

# osx 의 경우 credential 을 키체인(keychain access.app)으로도 관리한다.
# ~/.git-credential 내용이 osx의 키체인으로 등록된다.
# 현재 저장소의 키체인에 저정된 id,pw 를 확인한다.
git credential-osxkeychain get

# 수동으로 github.com 키체인 삭제(마지막에 엔터 2번입력해야 반영된다.)
git credential-osxkeychain erase
host=github.com
protocol=https

# 수동으로 github.com 키체인 등록(마지막에 엔터 2번입력해야 반영된다.)
git credential-osxkeychain store
host=github.com
protocol=https
username=ysoftman
password={깃헙 PAT(personal access token}

# 참고로 git push 되지만 다음과 같은 에러가 발생하는 경우가 있는데
# ~/.git-credentials newline 을 제거해야 한다.
warning: url has no scheme:
fatal: credential url cannot be parsed:

#####

# 새로운 git repository 생성(.git 디렉토리가 생성됨)하고 원격 저장소로 푸시
git init
git add -A
git commit -m "first commit"
git remote add origin git://github.com/ysoftman

# -u (--set-upstream)
git push -u origin master

# remote(origin) 저장소 변경
git remote set-url origin git://github.com/ysoftman

# 이미 존재하는 git repository 저장소를 로컬에 복사
# git 프로토콜 외 ssh, https 등 사용가능
# --recursive 옵션 사용시 링크된 repo 도 클론한다.
git clone git://github.com/ysoftman

# 클론 후 ysoftman1 브랜치로 체크아웃
git clone -b ysoftman1 git://github.com/ysoftman

# --single-branch 옵션까지 사용하면 해당 브랜치 커밋만 가져온다.
git clone -b ysoftman1 --single-branch git://github.com/ysoftman

# ssh 를 사용하는 경우
# 로컬에서 ssh 키 생성수 id_rsa.pub 를 github personal setting -> ssh and gpg key -> new ssh key 에 추가하고 다음과 같이 클론한다.
git clone git@github.com:ysoftman/ysoftman.git

# 파일 추가(스테이지에 올리기)
git add source_file.c

# 변경(수정,삭제) 있는 파일만 추가(tracked 파일중)
git add -u

# 전체 파일 추가(untracked 파일까지 포함)
git add -A

# 수정된 파일 자동 스테이지 추가하여 커밋
git commit -a

# 로컬 저장소에 반영(커밋)
git commit -m "commit comment."

# 마지막 커밋 내용 수정(push 이미 푸시 커밋은 수정하지 말자.)
git commit --amend

# 변경사항 없는 컷밋하기
git commit -m "no changes" --allow-empty

# a1234(git log 로 커밋 해시 확인) 커밋 되돌리기
# a1234 커밋 상태로 커밋한다.(자동 커밋되기 때문에 주의, reset 으로 커밋 취소 가능)
# a1234 revert 가 앞에 붙은 커밋 메시지를 사용한다.
git revert a1234

# 자동 커밋하지 않고 되돌리기
git revert --no-commit a1234

# 마지막 커밋 1개 되돌리기
git revert HEAD~1

# -X <option>, --strategy-option=<option>
# a1234(theirs)로 자동 커밋하지 않고 되돌리기
git revert -X theirs --no-commit a1234

# 머지 되돌리기
# 머지커밋을 보면 다음과 같이 브랜치의 시작(aaa)과 끝(ccc) 커밋이 명시되어 있다.
# Merge aaa ccc
# -m(--mainline) parent-number:머지된 브랜치의 시작 커밋aaa는 1이 된다.
git revert -m 1 머지커밋해시

# 현재 로컬 브랜치를 리모트에 푸시
git push

# pre-push hook 하지 않고 푸시하는 경우
git push --no-verify

# 현재 로컬 모든 브랜치를 리모트에 푸시
git push --all

# 로컬 저장소 develop 브랜치를 리모트 저장소 develop 로 푸시
# git push {remote_name} {local_branch}:{remote_branch}
git push origin develop:develop

# 현재 로컬 모든 tag들 리모트에 푸시
git push --tags

# 리모트 저장소 브랜치 내용을 로컬 브랜치에 반영(fetch + merge)
git pull

# Fetch all remotes (브랜치가 최신으로 업데이트되지는 않는다.)
git fetch --all
# 또는
git pull --all

# 리모트 저장소 master 를 로컬 master 로 pull 받기(최신으로 업데이트)
git pull origin master

# pull request 내용 받기(123 은 pr 번호다.)
git pull origin pull/123/head:pr-123

# 커밋 로그 보기
git log

# 커밋 로그 diff 도 보기(-p --patch 패치 생성)
git log -p

# 커밋 로그 diff 최신 10개 이전까지만 보기
# log 보기 화면에서 / 로 검색할 수 있다. 예) /my\ name\ is\ ysoftman
git log -p -10

# HEAD 에 tracked 파일들 보기
git ls-tree HEAD

# 스테이지에서 빼기
git reset

# 또는
# 새로 생긴 커맨드로 reset 보다 권장된다.
git restore --staged 파일명

# push 되지 않은 최근 커밋1개 취소
git reset HEAD~1

# 소스가 꼬였을때 서버 기준으로 강제로 업데이트 받기(이클립스 설정파일에서 자주 발생)
git reset --hard HEAD
git pull

# 원격 push된 잘못된 바로 이전 커밋(내역) 삭제하기
# 헤드로부터 1개 전까지 커밋 삭제(1개 이전 상태로 되돌린다.)
# 원격으로 강제 push
git reset --hard HEAD~1
git push -f

# 더이상 사용되지 않는 리모트 브랜치 제거하고 가져오기
git pull --prune
# 또는
git fetch --prune

# 리모트 브랜치 리스트 파악
git branch -r

# 로컬 브랜치 리스트 파악
git branch -a

# git branch -a 로 보면 remotes/origin/xxx 가 나오는데
# 리모트에서 삭제된 브랜치들을 로컬에 적용해 삭제할 수 있다.
git remote update --prune

# 브랜치 생성
git branch ysoftmanbranch1

# 존재하는 브랜치 체크아웃(에러 발생시 -f 옵션으로 강제 스위칭 가능)
git checkout ysoftmanbranch1

# 브랜치 생성하고 생성된 브랜치로 이동(체크아웃)
git checkout -b ysoftmanbranch2

# origin에서도 삭제된 브랜치로 체크아웃
git checkout 삭제된_브랜치_이름 커밋_해시값

# 생성된 브랜치 원격으로 처음으로 푸시하는 경우
git push --set-upstream origin ysoftmanbranch2

# 원격 브랜치가 있는경우 로컬에 체크아웃
# -t(track) 이 없으면 커밋이 안되고, 다른 브랜치로 체크아웃시 원격 브랜치가 로컬에서 사라진다.(git pull 로 최신 상태여야 한다.)
git checkout -t {업스트림이름}/{브랜치명}
git checkout -t origin/ysoftmanbranch3

# 태그로 체크아웃
git checkout tags/1.0.0

# 브랜치 삭제(삭제할 대상외의 브랜치로 스위칭되어 있어야 한다.)
git branch -d ysoftmanbranch1

# 브랜치 이름 변경
git branch -m ysoftman_old_branch ysoftman_new_branch

# 브랜치 이름 변경후 원격에도 반영할때
# 원격 브랜치 삭제
git push origin -d ysoftman_old_branch

# 이름 변경된 브랜치 원격 반영할때
git push origin ysoftman_new_branch

# 로컬 저장소 현재 디렉토리에서 지워진 파일 리스트 보기
git ls-files -d

# 로컬 현재 디렉토리에서 지워지거나 수정된 모든 파일 복구(참고로 svn 인경우 svn up)
git checkout ./

# 로컬 현재 디렉토리에서 지워지거나 수정된 특정 파일만 복구
git checkout -- ysoftman_file1.txt

# 로컬 특정 파일만 특정 시점으로 복구
git checkout 커밋해시값 -- ysoftman_file1.txt

# 리모트 저장소 정보 확인
git remote -v

# 리모트 저장소에 저장소 추가
git remote add new_remote_name remote_URL

# untracked 파일 삭제
# -f force, -d (directory)
git clean -fd

# 커밋전에 차이 보기(-U10, --unified=10 위아래 내용 10줄씩 보기)
git diff -U10

# ysoftmanbranch1 브랜치의 aaa.txt 파일과 차이 보기
git diff ysoftmanbranch1 -- aaa.txt

# 현재 상태
git status

# 현재 환경 상태
git show

# 커밋 내용 보기
git show 커밋해시

# 현재 변경내용 저장하고 HEAD 상태로 되돌리기
git stash save

# 변경 리스트 보기
git stash list

# 변경 내용 보기
git stash show

# 변경 내용 적용하기(stash 에 계속 유지)
git stash apply

# 변경 내용 꺼내기(stash 에서 삭제됨)
git stash pop

# a1234 b555 커밋 master 에 반영하기
git checkout master
git cherry-pick a1234 b555

# 로컬 태그 리스트
git tag

# 로컬 태그 원격 태그로 푸시
git push origin 1.1.1

# 원격 태그 리스트
git ls-remote --tags

# 로컬 태그 삭제
git tag --delete 1.1.1

# 로컬 0.0.1로 시작하는 태그 모두 삭제
git tag | grep "^0.1.1.*" | xargs git tag --delete

# 원격 태그(들) 삭제
git push --delete origin 1.1.1 1.1.2 1.1.3
# 또는 빈 태그를 푸시해도 삭제 된다.
git push origin :refs/tags/1.1.1

# 원격 태그 0.0.1로 시작하는 태그 모두 삭제
git ls-remote --tags | awk '{print $2}' | sed 's/refs\/tags\///' | grep "^0.0.1.*" | xargs git push --delete origin

# 0.0.1로 시작하는 태그들 로컬 태그삭제 후 원격태그도 삭제
delete_tags=$(git tag | grep "^0.1.1.*")
echo $delete_tags | xargs git tag --delete
echo $delete_tags | xargs git push --delete origin

# 대소문자 파일이름 변경
git mv --force ysoftman.TXT ysoftman.txt

#####

# 머지시 충돌 해결하기
# develop 을 최신으로 pull 해놓고 ysoftman123 에서 시작
git checkout develop
git pull
git checkout ysoftman123

# 방법1 - merge (커밋 히스토리 유지)
# develop -> ysoftman1 로 머지
git merge develop

# 충돌 부분 수정 수정
vim aaa.txt
# 또는
# develop <- ysoftman123 머지 상황에서 전략 옵션 사용하기
# -X <option>, --strategy-option=<option>
# 충돌부분 ysoftman123(theirs)로 덮어쓰기
git checkout develop
git merge -X theirs ysoftman123
# 또는
# 충돌부분 develop(ours)로 유지
git merge -X ours ysoftman123

# 커밋하고 푸시(커밋 메시지는 기본적으로 충돌 해결 내용으로 채워진다.)
git commit -a
git push

# 머지 취소할 경우
git merge --abort

# git pull 후 충돌발생시 머지 취소 후
# 현재 내가 변경한 사항으로 pull(머지)하기
git pull -s recursive -X ours

# 방법2 - rebase (ysoftman123 의 커밋들이 develop 이후 커밋들로 강제 변경된다.)
# ysoftman123 브랜치에서 develop 으로 rebase
git rebae develop

# 충돌 나는 부분을 확인
git status # 충돌되는 부분은 both modified 로 표시
git diff

# 충돌 부분 수정
vim aaa.txt

# 커밋(커밋 메시지는 기본적으로 충돌 해결 내용으로 채워진다.)
git commit -a

# rebase 계속해서 rebase 종료
git rebase --continue

# 강제 푸시, --force-with-lease 는 내 로컬에서 수정된게 아니면 덮어쓰지않아 --force 보다 안전하다.
git push --force-with-lease

#####

# 저장소 이전(migration)
# old 저장소 bare 로 클론 받기
git clone --bare https://github.com/ysoftman/old-repository.git

# new 저장소로 mirror 푸시
cd old-repository.git
git push --mirror https://github.com/ysoftman/new-repository.git

# old 저장소 삭제
cd ..
rm -rf old-repository.git

#####

# github wiki 이전
# old 저장소 wiki 클론 받기
git clone https://github.com/ysoftman/old-repository.wiki.git

# remote origin 을 new 저장소로 바꾸기
git remote set-url origin https://github.com/ysoftman/new-repository.wiki.git

# new 저장소 github -> wiki 생성하기
# Initial Home page 커밋이 발생하지만 강제 푸시하면 old 커밋히스토리만 남게된다.
# 참고로 -f 옵션없으면 "관계 없는 커밋 내역의 병합을 거부합니다" 에러가 발생한다.
git push -f

#####

# 패스워드 같은 민감한 데이터가 커밋,푸시돼 커밋히스토리 제거가 필요할때
# 모든 브랜치 및 태그에서 password.txt 파일 삭제 전 참고 및 주의사항
# 커밋에 password.txt 파일만 수정이 있었다면
# 커밋 히스토리 자체가 제거된다.
# 커밋에 password.txt 외 다른 파일 수정이 있었다면
# 커밋 히스토리는 있고 커멋내용에서 password.txt 파일만 제거된다.
# 로컬에 password.txt 도 삭제되니 rename 으로 백업해두자.
cp -v password.txt password.txt.bak
git filter-branch --force --prune-empty --index-filter 'git rm --cached --ignore-unmatch password.txt' --tag-name-filter cat -- --all

# 이제 강제 push 하면 원격 저장소에도 password.txt 관련 커밋 히스토리 또는 내용이 삭제된다.
git push -f

# filter-branch 삭제 후 원격 저장소에는 삭제됐지만
# 로컬 커밋 히스토리(git log --all)로 refs 모두를 보면 다음과 같이 백업이 있다.
# 참고로 git 은 ./git/refs 에 커밋해시(sha1,40자리의 hexadecimal)값 파일을 저장해 관리 한다.
refs/original/refs/remotes/origin/master 
refs/original/refs/heads/master

# 로컬 .git/refs 에 백업된 refs 삭제
git update-ref -d refs/original/refs/remotes/origin/master
git update-ref -d refs/original/refs/heads/master

#####

# rebase 로 브랜치 합치기(커밋들이 대상 브랜치(master)의 마지막 커밋 이후로 변경돼 커밋 이력이 깔끔해 진다.)
# ysoftmanbranch1 이 master 에 머지되기전
# ysoftmanbranch1 에서 master 로 rebase
# ysoftmanbranch1 브랜치가 아닌 master 로 기반으로 파생된 커밋으로 된다.
git checkout ysoftmanbranch1
git rebase master

# 만약 충돌이 발생하면, 충돌 수정후 rebase 계속
git rebase --continue

# 현재 HEAD 는 ysoftmanbranch1 커밋이다.
# master 에서 ysoftmanbranch1 을 머지하여 master 가 HEAD 가 되도록 한다.
git checkout master
git merge ysoftmanbranch1
# 만약 로컬에서 rebase 완료했는데 취소하고 싶다면 reflog 로 최근 rebase.. 바로전으로 HEAD 확인
git reflog
aaa111 HEAD@{1}: rebase: commit message
aaa222 HEAD@{2}: rebase: commit message
aaa333 HEAD@{3}: rebase: commit message
aaa444 (master) HEAD@{4}: rebase: checkout master
aaa555 (HEAD -> branch_test) HEAD@{5}: rebase: commit message
# reset 으로 rebase 전의 head 로 돌리면 된다.
git reset HEAD@{5}
# 참고로 위처럼 reflog 는 reset 외 commit 등 HEAD 변경 내용이 모두 기록된다.

#####

# fork 저장소에서 작업시
# 원본 저장소 최신 내용 fork 저장소에 반영하기
# upstream 으로 원래 저장소 추가
git remote add upstream "https://원본저장소"
git remote -v

# upstream 저장소 삭제
git remote remove upstream

# upstream 최신 내용 가져오기
git fetch upstream

# fork master 브랜치에 upstream 내용 머지
git checkout master
git merge upstream/master

# 현재 브랜치 upstream 으로 push 하기
git push -u upstream

#####

# 저장소 합치기
# 현재 저장소 서브디렉토리 aaa 생성해 https://github.com/ysoftman/simplePf 의 master브랜치 내용을 가져와 추가한다.
# 합쳐진 저장소의 커밋 히스토리까지 유지할 수 있다.
git subtree add --prefix=aaa https://github.com/ysoftman/simplePf master
git push

github ssh-key 등록하기

# repository https / ssh clone URL 확인 후
# git-bash 에서
# https 를 사용하여 로컬에 clone 생성
git clone https://github.com/ysoftman/ysoftmanCode.git
# 또는 ssh 를 사용하여 로컬에 clone 생성
# 참고로 github 의 ssh 는 git 아이디만 사용해야 한다.
git clone git@github.com:ysoftman/ysoftmanCode.git

# ssh 로 clone 을 만들때 다음과 같이 권한이 없다는 에러가 발생하는 경우
# "Please make sure you have the correct access rights"
# 다음과 같이 ssh-key 를 생성하도록 한다.
ssh-keygen -t rsa

# ssh key 를 생성하면 예)/c/Users/ysoftman/.ssh/id_rsa.pub 에 생성된다.
# 이 파일의 내용을 github.com 에서 추가한다.
https://github.com/settings/ssh

# 윈도우의 경우 에러가 발생한다.
# 다음과 같이 rsa 파일 위치를 github 에게 알린다.
ssh -i /c/Users/Administrator/.ssh/id_rsa git@github.com

# 접속되지 않는다면
# ~/.ssh/config 등으로 로컬에서 id_rsa 개인키를 사용하지 않을 수도 있으니
# debug1: Trying private key .. 부분을 확인해보자
ssh -v git@github.com

# 참고로 remote host 에 접속하기 위해서 id_rsa.pub 를 remote host 의 ~/.ssh/authorized_keys 에 추가한다.

SSH 패스워드 크랙 툴 hydra medusa

hydra, medusa 는 패스워드 크랙툴이면서 동시에 시스템 감사(auditor) 도구이기도 하다.
brute-force 방식으로 패스워드가 될 만한 워드리스트를 무식하게 대입하여 로그인을 시도한다.
병렬처리로 빠르고 telnet, ftp, ssh, 인터넷 공유기 등의 암호 크랙에 사용된다.

# hydra 소스 다운로드 http://www.thc.org/releases/hydra-7.4.2.tar.gz
# medusa 소스 다운로드 http://www.foofus.net/jmk/tools/medusa-2.1.1.tar.gz
# password list 다운로드 http://dazzlepod.com/site_media/txt/passwords.txt
# yum(Redhat계열), apt-get(Debian계열), port(OSX) 로도 설치 가능

# hydra 기본 사용법
# -l 사용자명
# -P 패스워드리스트 파일
# 서버명
# 서비스형식
# -V 시도하고 있는 id/password 화면에 보이기
# -f 패스워들 찾았으면 종료
hydra -l root -P passwords.txt 123.123.123.123 ssh -V -f

# medusa 기본 사용법
# -h 호스트명
# -u 사용자명
# -P 패스워드리스트 파일
# -M 사용모듈(medusa -d 로 확인 가능) ssh 모듈이 없다면 libssh 설치
medusa -h 123.123.123.123 -u root -P passwords.txt -M ssh

# libssh  설치
# port 이용시
sudo port install libssh2
# apt-get 이용시
sudo apt-get install libssh-dev
# 그외 http://www.libssh2.org/ 에서 다운받고 빌드및 설치

Linux rsync 사용

# 설정 파일 수정
sudo vi /etc/xinetd.d/rsync
disable = no

# 원격 호스트의 rsyncd.conf 수정 (없으면 생성)
sudo vi /etc/rsyncd.conf
[test1]
path = /home/ysoftman/test1 #rsync 할 경로
uid = ysoftman #rsync 실행할 유저
gid = ysoftman #rsync 실행할 그룹
use chroot = yes
read only = yes
max connection = 5
timeout = 300

# rsync 포트 설정 변경
sudo vi /etc/services
rsync           10000/tcp

# 재시작
sudo /etc/init.d/xinetd restart

# 원격 호스트 -> 로컬호스트 경로로 가져오기(복사하기)
# -a 파일 속성(퍼미션, 소유자..) 유지
# -r 리커시브
# -v verbose
# -z 압축하여 전송
# --progress 진행상황 표시
# --exclude="*.o" .o 파일은 제외
# --exclude="*.so" .so 파일은 제외
# --bwlimit=10000 10000KBPS 대역폭 제한
# ysoftman@host: 형식을 사용하면 ssh(22번포트) 를 사용하게 된다.
rsync -arvz --progress --exclude="*.o" --exclude="*.so" --bwlimit=10000 ysoftman@remotehost:/home/ysoftman/test1/ ./test1

# 로컬 호스트에서 원격 호스트의 test1 설정이용하여 복사해오기
rsync -avz --progress --bwlimit=10000 --port=10000 remotehost::test1 ./test1 ./

# 로컬의 apple,lemon 디렉토리 -> 원격호스트 apple,lemon 디렉토리에 복사
# -R, --relative  use relative path names
ssh ysoftman@remotehost "mkdir -p test1/{apple,lemon}"
rsync -avz --relative apple/* lemon/* ysoftman@remotehost:~/home/ysoftman/test/

# ssh -i .pem 파일로 접속하는 원격호스트에 복사하기
# -e, --rsh=COMMAND  specify the remote shell to use
rsync -avz --rsh="ssh -i ~/.ssh/ysoftman-remotehost.pem" ysoftman.txt ysoftman@remotehost:/home/ysoftman/