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

late.sh terminal clubhouse

ssh 접속하면 터미널 공간에서 채팅하고 음악도 듣고, 갤러리도 보고 만들고 게임도 하고 그런 휴식처가 late 다

# late 설치하고 접속
curl -fsSL https://cli.late.sh/install.sh | bash
late

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.

# 로컬에서 사용하는 다양한 종류의 터미널 프로그램이 TERM=고유의터미널값 을 사용하는 경우
# TERM=xterm-256color 로 설정된 원격 서버에 ssh 접속 할때
# 컬러가 안보이고 키 입력이 제대로 안되는 문제가 발생할 수 있다.

# 다음과 같이 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/collections/ansible/builtin/ssh_connection.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"
# 원격 url 특정 이름으로 설정해서 내 로컬에서 사용한다.
# origin 내저장소를 나타내는 관례적인 이름이다. 다른 이름을 사용해도 된다.
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 add 파일로 staging 하고 마지막 커밋 내용을 수정하면 추가된다.
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

# 리모트 저장소 브랜치 커밋을 로컬 브랜치로 가져오지만 로컬 브랜치와 머지되지는 않는다.
# 로컬 HEAD -> main (로컬) 인 상태에서
# fetch 로 받은 별도의 origin/main origin/develop .. 등이 존재하게 된다.
# git merge origin/HEAD 하면 HEAD -> origin/main 로 변경된다.
git fetch

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

# Fetch all remotes
git fetch --all
# 또는
git pull --all

# origin 내용이 로컬과 달라 pull 경고 발생시
git config pull.rebase true 하고 git pull
# 또는
git pull --rebase

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

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

# 참고로 원본 원격 저장소 이름은 관례적으로 upstream 라는 이름을 쓴다. 이름을 변경해도 상관없다.
# fork 해서 내 contribute commit 이 원본에 머지 된 후 원본 의 내용을 반영할때
# --ff (fastforward 브랜치 포인터만 앞(최신)으로 이동) 이 기본 옵션으로 ff 가능하지 않으면 merge commit 을 생성한다.
git pull upstream
# --ff-only 를 사용하면 ff 가 안되면 에러 발생시켜 원본 main 브랜치와 같은 커밋 상태를 유지할 수 있도록 한다.
git pull --ff-only upstream

# 커밋 로그 보기
git log

# 최근 5일 전 로그 보기(--oneline 커밋내용을 한줄로 표시)
git log --since="5 days ago" --oneline

# 커밋 로그 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

# 소스가 꼬여 pull 이 안될때 현재 변경사항 리셋후 pull 받기(이클립스 설정파일에서 자주 발생)
# 로컬 기준으로 리셋하는 경우
git reset --hard HEAD
# origin 기준으로 리셋하는 경우
git reset --hard origin/master
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

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

# ysoftmanbranch1 기준에서 ysoftmanbranch2 브랜치로 생성 이동(체크아웃)
git checkout -b ysoftmanbranch2 ysoftmanbranch1

# 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 checkout {브랜치명} -- {파일경로}

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

# 로컬에 있는 원격 브랜치 삭제(실제 원격 브랜치는 삭제되지 않는다.)
git branch -d ysoftman_old_branch --remote

# 브랜치 이름 변경
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

# 브랜치 2개에서 특정 파일들만 차이 보기
git diff release-0.1.0 release-0.2.0 -- $(find aaa/*/readme.md)

# 브랜치 2개에서 특정 파일들만 차이 보기(origin 브랜치와 비교시) 
git diff origin/release-0.1.0 release-0.2.0 -- $(find aaa/*/readme.md)

# 특정 파일은 제외하고 차이 보기
# git diff, git log, git add 등 명령어 뒤에 오는 파일/디렉터리 지정을 pathspec
git diff ":(exclude)파일명1" ":(exclude)/path/to/파일명2"

# 특정 브랜치에서 grep 하기
git grep abc release-0.1.0 aaa/*/readme.md | sed "s/$branch_name://"

# 현재 상태
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

# rebase
git rebaes -i 특정 커밋

# root 부터 rebase
git rebase -i --root

# rebase 커밋 화면에서 수정할 커밋 edit 등으로 수정 후 진행하여 작성자 변경하기
# edit 개수만큼 반복
git rebase --continue
git commit --amend --author="ysoftman <ysoftman@gmail.com>" --no-edit

# author date 변경하는 경우
git commit --amend --no-edit --date="2021-04-21T16:06:31"

# commit date 변경하는 경우 
GIT_COMMITTER_DATE="2021-04-21T16:09:00" git commit --amend --no-edit

# 강제 푸시
git push -f

# 태그 리스트
git tag

# 태그 버전이름으로 정렬된 리스트
git tag --sort=version:refname

# 로컬 태그 원격 태그로 푸시
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

# update-ref 는 안전장치(물어보지 않고 수정)가 없어서 왠만하면 사용하지 않는것이 좋다.
# 다음과 같은 브랜치 생성을 update-ref 로 할때
# git branch ysoftman_new 
# git branch -f ysoftman_new 
git update-ref refs/heads/ysoftman_new HEAD_또는_커밋해시등

# git branch --remote 에서 로컬에만 보이는 브랜치를 삭제시
git update-ref -d refs/remotes/aaa/100
git update-ref -d refs/remotes/bbb

#####

# 머지시 충돌 해결하기
# 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 rebase develop

# 또는 origin/develop 최신내용을 기준으로 한다면
git rebase origin/develop

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

# 충돌 부분 수정
vim aaa.txt

# git commit 을 하면 git이 원래 이어 붙이려던 기존 커밋 흐름 외 충돌 해결용 새로운 커밋이 붕 떠서 끼어들어가 버린다.
# 이로 인해 rebase 프로세스가 꼬이거나 히스토리가 지저분해질 수 있으니 커밋 대신 git rebase --continue 를 사용한다. 
# 계속 사용해서 더 이상 continue 하게 없으면 끝
git rebase --continue

# 강제 푸시, --force-with-lease : 원격 브랜치가 내가 마지막으로 본 상태일 때만 덮어쓴다. 그 사이 다른 사람이 이 브랜치에 push 했다면 실패해서 남의 커밋을 날리는 사고를 막아준다.
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 main 브랜치에 upstream 내용 머지
git checkout master
git merge --ff-only upstream/main

# fork main 원격 브랜치로 푸시
git push origin main

# 현재 브랜치 upstream 으로 푸시(이건 기여할 원본 저장소에서 PR 리뷰 과정을 통과해서 담당자가 github 에서 머지해야 된다.)
git push -u upstream

#####

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

#####

# git worktree : Git 2.5 버전(2015년 7월 릴리스)부터 공식적으로 도입
# 생성된 워크트리 리스트
git worktree list

# ../abc 위치에 현재 브랜치의 복사본 만들고 브랜치 이름이 abc 가 된다.
git worktree add ../abc

# ../abc 위치에 main 브랜치의 복사본 만들기
git worktree add ../abc main

# ../abc 위치에 main 브랜치의 복사본을 foobar 브랜치이름으로 해서 복사본 만들기
git worktree add ../abc main -b foobar

# ../abc 워크트리 삭제
git worktree remove ../abc

# ../abc 등의 워크트리를 수동으로 삭제해 제대로 정리되지 않았을때 정리
git worktree prune

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/ 에서 다운받고 빌드및 설치

Prev