git 명령어
git를 사용하면서 잊어버리는 명령들을 하나씩 기록해두고자 작성합니다.
“`git status“`
해서 원하는 파일을 찾고,
“`git rm –cached“`
으로 staging area
에 있는 파일을 지울 수 있습니다.
물론 실제 파일은 지워지지 않습니다.
git를 사용하면서 잊어버리는 명령들을 하나씩 기록해두고자 작성합니다.
“`git status“`
해서 원하는 파일을 찾고,
“`git rm –cached“`
으로 staging area
에 있는 파일을 지울 수 있습니다.
물론 실제 파일은 지워지지 않습니다.
배열(array)
과 슬라이스(slice)
Go언어에 배열과 슬라이스에 대해 알아보겠습니다.
Go언어는 많은 객체 지향 언어에서 기본으로 지원하는 list타입이 없고, 배열과 슬라이스가 존재합니다.
배열을 선언하는 법은 먼저 배열의 길이를 선언하고, 타입(type) 뒤에 초기화 할 값을 넣어줍니다.
array := [5]int{1,2,3,4,5}
array := […]int{1,2,3}
위의 형태로 사용합니다.
Go언어는 일반적으로 알고 있는 (C, Java와 같은) 언어들과 type declaration Syntex
가 반대입니다.
golang
의 syntex에 대한 설명은 아래 링크를 참고하시면 됩니다.
golang syntex에 대해
위의 배열 선언 코드를 보면 익숙하지 않는 연산자가 나옵니다.
:-
위의 연산자는 변수의 선언과 할당을 동시에 할때 사용하는 연산자로 Go언어에서 자주 쓰입니다.
앞으로 Go언어에 대한 코드를 볼때 자주 접하게 될겁니다.
slice := []int
slice
는 동적 배열의 개념으로 만들어진 것으로 빠르고 효과적으로 배열의 크기를 늘리거나 줄일 수 있습니다.
append
라는 내장 함수를 이용해서 데이터를 추가 할 수 있으며, 아래 보이는 형태를 이용해서 slice
를 쉽게 잘라낼 수도 있습니다.
slice := []int{1,2,3,4}
newSlice := append(slice, 5) // newSlice는 [1,2,3,4,5]
newSlice2 := slice[1:2] // newSlice2는 [2,3]
위의 두 가지를 보면 배열과 슬라이스의 차이를 명확하게 알수 있습니다.
배열은 사이즈를 정확히 지정해야하고, 슬라이스는 사이즈를 지정할 필요가 없습니다.
즉, 사이즈를 지정하면 배열로 선언이 되고, 사이즈를 지정하지 않는다면 슬라이스로 선언이 되는 것입니다.
슬라이스의 특징을 알아보기 위해 슬라이스의 주소값을 출력하는 샘플코드 입니다.
package main
import (
"fmt"
)
func testArray(array [5]int) {
fmt.Printf("in testArray() func %p\n", &array)
}
func testSlice(slice []int) []int {
fmt.Printf("in testSlice() func %p\n", slice)
return append(slice, 6)
}
func main() {
array := [5]int{1, 2, 3, 4, 5}
fmt.Printf("origin ptr: %p\n", &array)
testArray(array)
// 배열을 슬라이스로 변환, 메모리 주소는 현재까지 동일함
slice := array[:]
fmt.Printf("%v, %p\n", slice, slice)
slice2 := testSlice(slice)
// 메모리가 변함. 새로 할당 한 듯
fmt.Printf("%v, %p\n", slice2, slice2)
// 이후부터는 같음
slice2 = append(slice2, 7)
fmt.Printf("%v, %p\n", slice2, slice2)
}
처음 배열을 선언하고 메모리 주소를 확인하고, 이후 슬라이스로 변환하고, 슬라이스의 데이터를 변환하면서 주소를 확인해 가는 코드입니다.
output
origin ptr: 0xc420012180
in testArray() func 0xc4200121b0
[1 2 3 4 5], 0xc420012180
in testSlice() func 0xc420012180
[1 2 3 4 5 6], 0xc420016140
[1 2 3 4 5 6 7], 0xc420016140
실행결과는 위와 같습니다.
간단히 해석하자면,
origin ptr: 0xc420012180
in testArray() func 0xc4200121b0
함수 실행시 넘긴 배열인자의 주소를 확인한 결과 주소가 변했습니다.
이 경우는 callbyvalue
로 함수를 호출하게 되어 배열를 deep copy하므로 주소가 변한 것입니다.
배열과 슬라이스의 callbyvalue
, callbyreference
에 대한 내용은 아래에서 다른 예제코드로 보도록 하겠습니다.
[1 2 3 4 5], 0xc420012180
in testSlice() func 0xc420012180
슬라이스로 변환한 결과 배열과 주소는 동일합니다.
이 경우는 결국 타입만 변경된 것입니다.
실제 주소는 같습니다. 결국 내부 데이터를 array
에서 바꾼다고 하면, slice
의 값도 변할 것입니다.
[1 2 3 4 5 6], 0xc420016140
[1 2 3 4 5 6 7], 0xc420016140
여기서 부터 재미있습니다.
testSlice(...)
함수를 호출했을 때 내부에서 append
라는 내장 함수를 호출합니다.
append
는 slice에 값을 추가할 때 사용하는 내장함수로len
,cap
등과 함께 자주 접하게 될 것입니다.
append
함수를 호출하고 return
을 하게 되면 새로운 slice
가 반환하게 됩니다.
[1 2 3 4 5 6], 0xc420016140
보면 주소가 변경 되었다는 것을 알수 있습니다.
그런데!!, 두번째 append
호출했을 때는 주소가 그대로 인 것을 알 수 있습니다.
[1 2 3 4 5 6 7], 0xc420016140
slice
는 기본적으로 length
와 capacity
를 가지고 있는데, 이것에 대한 상세한 설명은 두개의 링크로 대신합니다.
Go Slices: usage and internals
Arrays, slices (and strings): The mechanics of ‘append’
둘의 가장 큰 차이점입니다.
배열은 인자(argument)로 받을 경우 callbyvalue
로,
슬라이스는 callbyreference
로 받게 됩니다.
이 것을 눈으로 확인해보기 위해 간단한 샘플코드를 만들었습니다.
func testArray(array [1e7]int)
* 천만개의 배열을 복사func testSlice(slice []int)
* 포인터만 복사
callbyvalue
와callbyreferrence
를 단순비교하기 위해서는
위의 샘플코드처럼 배열과 슬라이스의 주소를 확인하기면 하면 되지만,
배열과 슬라이스를 함수에서 사용할 때 둘 사이의 차이를 쉽게 느껴보고자 아래 코드를 만들었습니다.
package main
import (
"fmt"
"time"
)
func callByValue(array [1e7]int) int64 {
return time.Now().UnixNano() / int64(time.Millisecond)
}
func callByReference(slice []int) int64 {
return time.Now().UnixNano() / int64(time.Millisecond)
}
func main() {
array := [1e7]int{}
t := time.Now().UnixNano() / int64(time.Millisecond)
t2 := callByValue(array)
fmt.Printf("call by value elapsed time : %f\n", float32(t2-t)/1000)
t = time.Now().UnixNano() / int64(time.Millisecond)
slice := array[:]
t3 := callByReference(slice)
fmt.Printf("call by reference elapsed time : %f\n", float32(t3-t)/1000)
}
output
call by value elapsed time : 0.043000
call by reference elapsed time : 0.000000
큰 배열을 인자로 넘겨야하는 경우, 배열은 전체복사가 된다는 점을 알고 있어야 합니다.
여기까지가 배열과 슬라이스에 대한 간단한 정리였습니다.
최근, 회사에서 Go언어를 쓰게 되어서 간단하게 Go언어에 대해서 간단하게 포스팅 해보려합니다.
저도 많은 내용을 아는 것은 아니니 부족한 부분이 많을 것입니다.
이 글은 정리차원에서 적어두는 것이나, Go언어를 잘 모르시는 분, Go언어에 관심이 가는 분, 또는 Go언어를 배워보고 싶은 분들께 유익한 글이 되었으면 합니다.
새로운 언어를 배울 때 가장 먼저 확인하는 hello world 입니다.
Go 놀이터에 가셔서 확인하실 수 있고, 웹상에서 테스트도 가능합니다.
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, playground")
}
위의 코드를 보면 Java처럼 현재 파일의 패키지를 설정하고 있고
import 로 사용할 패키지를 지정, main 함수가 기본 프로그램 엔트리 포인트입니다.
특이한 것이 main함수에 인자가 없습니다.
인자(ARGV)를 받기위해서는os package
를 import 해야합니다.
Go언어는 컴파일 기반의 정적 타입언어입니다.
이는 컴파일로 인해파이썬(Python)
이나루비(Ruby)
같은인터프리터(interpreter)
언어로 개발할 때보다 버그 요소가 많이 줄어듬을 의미합니다.
물론 컴파일언어의 특징인 빠른 속도 또한 당연합니다.
특히 Go언어의 컴파일러는 C언어에서의 warning (예를 들면, 사용하지 않는 변수나 패키지를 import했을시에 Go 컴파일러는 오류를 발생시킵니다.) 에 해당하는 문제들도 모두 error로 만듭니다.
- Go언어는 컴파일 언어지만,
C/C+
의 해더파일이 없어서 헤더파일이 조금만
수정되어도 모두 다시 컴파일하는 그런 문제가 없고, 소스코드를 패키지화하여 변경된 부분만 컴파일하기 때문에 컴파일 시간이 엄청나게 빠릅니다. -> How does Go compile so quickly?
Go언어는
interface
가 있지만 따로 선언은 하지 않습니다. -> Duck Typing
선언이 없이 인터페이스의 함수를 구현하면 그 인터페이스를 사용한다고 간주합니다.
예를 들어notifier interface
가 정의되어 있습니다.
이notifier interface
는notify()
메소드를 가지고 있습니다.
- 특정
struct
에서notify()
메소드를 구현했다면,
이struct
는notifier interface
를 구현했다고 간주하는 것입니다.
Go언어는 상속이 없습니다.
Go언어에서 일반적인 객체 지향 언어에서의class
의 역할을struct
가 맡고 있습니다.
Go의struct
는 상속이 되지 않습니다. 대신composition
이라는 것이 존재합니다.
composition
이란?
한 타입과 다른 타입을 결합해서 사용할 수 있게 해주는 것을 의미합니다.
이는 각 타입간의 결합도를 낮춰주는 효과가 있습니다.
일반적으로 상속을 사용해서 코딩을 하게 되면class
간의 관계가tree
형태로 만들어집니다.
따라서 상속을 계속 할수록 계층 구조가 점점 복잡해지고, 그 상황에서 여러가지 문제점이 발생할 수 있습니다.
`compositio“의 중요성 -> Prefer composition over inheritance?
Go언어는 바이너리 빌드시 가비지 콜렉터를 내장합니다.
그래서C/C++
처럼 개발자가 메모리 할당 및 해제를 신경쓰지 않아도 됩니다.
또한,Java
처럼 가상머신이 필요하지도 않기 때문에,C/C++
처럼 빠른 성능을 기대할 수 있습니다.
최근은 대부분의 컴퓨터가 멀티코어인 시대입니다.
이에 맞게 Go언어는 멀티코어 환경 지원을 위해 만들어진 언어입니다.
Go는Goroutine
이라는 논리적 쓰레드(Thread)를 기본적으로 제공합니다.
사용자는 멀티코어 및 쓰레드 사용에 대해 고민하지 않고,Goroutine
을 사용하면 Go 런타임이 알아서 현재 cpu의 코어에 맞춰서 동시에 코드를 실행해줍니다.
Thread를 만들고 실행하고 종료하고 하는 별도의 불편한 과정이 필요없습니다. 사용자는 손쉽게 멀티코어를 이용할 수 있습니다.
이후 포스팅은 다음 포스팅에 하겠습니다.
맥북에서 sublime text3(서브라임 택스트)를 사용하다가 문제가 생겼습니다.
맥의 finder에서 파일명을 복사하다가 한글이 분해(?)되는 문제입니다.
스크린샷 이라는 글자가 ㅅㅡㅋㅡㄹㅣㄴㅅㅑㅅ 으로 변하는 마법…
기본적으로 지원하는 메모 앱에서는 정상 동작해서 좀 찾아봤더니 맥은 윈도우즈나 리눅스(linux)와는 별도의 UTF8 방식을 채용하고 있었습니다.
맥은 UTF8을 사용하지만 NFD(Normalization Form Canonical Decomposition)라는 방식으로 정규화를 하고,
일반적인 UTF8은 NFC(Normalization Form Canonical Composition)방식을 사용하기 때문에 서브라임에서 한글이 전부 풀어지는 문제가 발생한 것이었습니다.
해결책을 찾던 중 한 일본인의 Sublime text3 Plugin 을 발견!!
https://github.com/astronaughts/SublimeNFDToNFCPaste
설치는 sublime text 3
실행 > Preferences
> Browse Packages
를 눌러서 sublime의 플러그인 설치 경로를 알아내거나
/Users/admin/Library/Application Support/Sublime Text 3/Packages
위의 경로로 들어가면 됩니다.
해당 경로에서
# git clone https://github.com/astronaughts/SublimeNFDToNFCPaste SublimeNFDToNFCPaste
실행하시면 됩니다;; 쉽죠? ㅎㅎㅎ
소스 한번 확인해봤더니 달랑 5줄 ㅎㅎㅎ
class NfdToNfcPasteCommand(sublime_plugin.TextCommand): def run(self, edit): paste = sublime.get_clipboard() sublime.set_clipboard(unicodedata.normalize('NFC', paste)) self.view.run_command('paste')
붙여넣기할때 NFC로 문자열을 변경해주네요.
앞으로 유용하게 쓸꺼 같습니다.
참고
mysql 사용자 추가 생성 가끔식 하는데 항상 잊어버린다.
해서 기록을 위해 여기 글을 작성한다.
create user 'userid'@'%' identified by 'password';
grant all privileges on *.* to 'userid'@'%';
grant all privileges on dbname.* to 'userid'@'%';
CREATE DATABASE `dbname` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
flush privileges;
앞으로는 이걸보고 하면 되겠다.
$> sudo yum install -y epel-release $> sudo rpm -ivh http://rpms.remirepo.net/enterprise/remi-release-7.rpm $> sudo yum --enablerepo=remi update remi-release
$> sudo systemctl start redis.service $> sudo systemctl enable redis.service $> sudo systemctl status redis.service
status 실행 후
● redis.service - Redis persistent key-value database Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled) Drop-In: /etc/systemd/system/redis.service.d └─limit.conf Active: active (running) since Thu 2016-06-30 16:31:27 KST; 1 weeks 3 days ago
위처럼 active 상태가 나타나면 정상 동작 중이다.
$> sudo yum install -y postgresql-server postgresql-contrib postgresql-libs postgresql-devel $> sudo postgresql-setup initdb $> sudo systemctl start postgresql $> sudo systemctl enable postgresql $> sudo systemctl status postgresql
postresql 도 위의 redis와 마찬가지로 active 상태가 나오면 정상동작 중이다.
루비 설치가 필요하다. 상세 내용은 예전 포스팅을 참조한다.
http://weeppp.com/?p=93
$> sudo gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 $> sudo curl -sSL https://get.rvm.io | sudo bash -s stable
rvm 그룹에 자신의 user id를 추가한다.
$> sudo vi /etc/group
... rvm:x:505:user,user2,user3
logout 후 재접속 한다. 환경 설정 리로드를 위함
# restart $> type rvm | head -n 1
rvm is a function
위의 내용이 출력되면 정상 설치
$> rvm install 2.3.1 $> rvm use 2.3.1@newgemset --create --default $> gem update $> gem install bundler
$> curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash # exit the terminal and open it again
logout 후에 다시 재접속한다.
$> nvm install 6.2.0 $> nvm alias default 6.2.0 $> npm install -g svgo phantomjs-prebuilt
하단 링크 참조
https://github.com/discourse/discourse/blob/master/docs/DEVELOPER-ADVANCED.md
필요한 라이브러리들 설치
$> sudo yum install -y expect git-core ImageMagick* advancecomp gifsicle jhead jpegoptim optipng pngcrush pngquant
db 설정
여기서는 development, production database를 모두 만든다.
하단 ‘password’ 부분에 원하는 암호를 입력한다.
$> whoami > /tmp/username
$> sudo su postgres $> createuser --createdb --superuser -Upostgres $(cat /tmp/username) $> psql -c "ALTER USER $(cat /tmp/username) WITH PASSWORD 'password';" $> psql -c "create database discourse_development owner $(cat /tmp/username) encoding 'UTF8' TEMPLATE template0;" $> psql -c "create database discourse_test owner $(cat /tmp/username) encoding 'UTF8' TEMPLATE template0;" $> psql -c "create database discourse owner $(cat /tmp/username) encoding 'UTF8' TEMPLATE template0;" $> psql -d discourse_development -c "CREATE EXTENSION hstore;" $> psql -d discourse_development -c "CREATE EXTENSION pg_trgm;" $> psql -d discourse -c "CREATE EXTENSION hstore;" $> psql -d discourse -c "CREATE EXTENSION pg_trgm;" $> exit
discourse 설치
$> git clone https://github.com/discourse/discourse.git ~/discourse $> cd ~/discourse $> bundle install $> bundle exec rake db:create db:migrate db:test:prepare
개발 모드로 실행 확인
$> bundle exec sidekiq -d -L log/sidekiq.log -C config/sidekiq.yml $> thin start
이제 배포판을 설치해보려고 한다.
실제 이 포스팅은 production 모드 설치를 위해 쓰고 있는 것이므로 지금부터가 진짜다;;
설정 파일 생성
$> cd $(discourse_home)/config $> cp discourse_defaults.conf discourse.conf
설정파일 수정
$> vi discourse.conf
# username accessing database db_username = user_id # password used to access the db db_password = password ... # hostname running the forum hostname = "weeppp.com" ... # enable if you really need to serve assets in prd serve_static_assets = true
sidekiq 설정
$> vi sidekiq.yml
--- :pidfile: tmp/pids/sidekiq.pid staging: :concurrency: 10 production: :concurrency: 20 development: :concurrency: 10 :queues: - [critical,4] - [default, 2] - [low]
production mode db생성
$> cd ~/discourse $> RAILS_ENV=production bundle exec rake db:create db:migrate db:test:prepare
nil:class 에러가 나오던데 별 문제는 아니었던 것 같다.
관련 포스트가 meta.discourse.org 에 있었던 것 같으니 찾아보길 바란다.
sidekiq production mode 실행
$> bundle exec sidekiq -d -L log/sidekiq.log -C config/sidekiq.yml -e production
관리자 테스트 계정 생성
$> cd ~/discourse $> cp db/api_test_seeds.rb db/seeds.rb $> RAILS_ENV=production bundle exec rake db:seed $> RAILS_ENV=production rails c > u = User.last > u.activate > u.save > quit
80포트로 실행하기 위해서는 root 권한이 필요한데 이때 postgresql 인증 문제가 발생한다.
postgresql 인증설정 변경이 필요하다. 하단 링크 참조
postgresql 설정 변경
$> sudo /var/lib/pgsql/data/pg_hba.conf
local all postgres peer
Should be
local all postgres md5
$> sudo systemctl restart postgresql
에셋 빌드
$> RAILS_ENV=production bundle exec rake assets:precompile
thin 서버 실행
$> rvmsudo rails server thin -b 0.0.0.0 -p 80 -e production
http://ftp.daumkakao.com/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-1511.iso
$ sudo yum install -y mariadb mariadb-server
$ sudo systemctl start mariadb
$ sudo mysql_secure_installation
mysql_secure_installation prompts: Enter current password for root (enter for none): OK, successfully used password, moving on... Setting the root password ensures that nobody can log into the MariaDB root user without the proper authorisation. New password: password Re-enter new password: password Password updated successfully! Reloading privilege tables.. ... Success!
$ sudo systemctl enable mariadb
$ sudo vi /etc/my.cnf.d/client.cnf
[client] default-character-set=utf8
$ sudo vi /etc/my.cnf.d/server.cnf
[mysqld] collation-server = utf8_unicode_ci init-connect='SET NAMES utf8' character-set-server = utf8
$ sudo systemctl restart mariadb
$ sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
$ sudo yum install nginx
$ sudo systemctl start nginx $ sudo systemctl enable nginx
yum install -y epel-release rpm -ivh http://rpms.remirepo.net/enterprise/remi-release-7.rpm yum --enablerepo=remi update remi-release yum --enablerepo=remi-php70 install -y php php-fpm php-mysql php-gd php-common php-cli php-json php-opcache php-devel php-imagick
$ sudo vi /etc/php.ini
cgi.fix_pathinfo=0
$ sudo vi /etc/php-fpm.d/www.conf
listen = /var/run/php-fpm/php-fpm.sock listen.owner = nginx listen.group = nginx user = nginx group = nginx
$ sudo vi /etc/nginx/nginx.conf
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name server_domain_name_or_IP;
root /usr/share/nginx/html;
index index.php index.html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
try_files $uri $uri/ /index.php?/$request_uri;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
location ~ .php$ {
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /.ht {
deny all;
}
}
$ sudo systemctl restart nginx
/usr/share/nginx/html/
$ sudo yum install unzip
$ sudo unzip ciboard.zip
가끔 UTF-8문서에 한글이 들어가 있을 경우에 파일을 열면 한글이 깨져서 나올때가 있다.
이는 한글이 들어있는 UTF8로 인코딩된 파일에 BOM이 없어서 UTF8로 읽어야하는지를 몰라서 발생하는 현상이다. BOM이라는 놈이 직접 넣어주기엔 매번 귀찮다.
그래서 이렇게 웹에서 자바스크립트로 BOM을 넣어주도록 했다.
텍스트 파일에 간단히 BOM을 넣어주고 싶을 경우 이용하자.
예전 포스팅에서 git 서버 구축하고 ssh로 접속하는 것 까지 포스팅했었다.
그런데 linux에서 git를 커맨드로 직접 다루려니 비번을 자꾸 물어봐서 너무 스트레스를 받았다.
그래서 ssh를 패스워드 대신 공개키 기반 인증으로 사용하기로 했다.
1. 클라이언트 설정(리눅스)
$ ssh-keygen -t rsa -b 4096 -C "weep@weeppp.com"
본인의 이메일을 입력하고 위 명령 실행하면 키가 생성되는데
첫번째 입력은 key의 이름이고, 두번째는 비밀번호 설정 유무인데, 입력안할꺼면 엔터치면 된다.
git.key git.key.pub
필자는 git.key라는 이름으로 생성했더니 이렇게 두개의 파일이 생성되었다.
첫번째는 개인키고, 두번째 pub 확장자 파일은 public key, 즉 공개키이다.
두개의 파일을 ~/.ssh 폴더에 위치시킨다. 폴더가 없으면 생성한다.
다음으로 ssh-agent 실행유무를 확인하자.
$ eval $(ssh-agent -s) Agent pid 2933
위처럼 pid가 나온다면 정상적으로 실행중인 것이다.
$ ssh-add ~/.ssh/git.key
위의 명령이 정상적으로 실행되었다면 이제 password대신 rsa키를 이용해서 ssh접속이 가능해진 것이다.
2. 서버 설정
클라이언트의 설정만으로는 물론 서버에 접속이 가능할리가 없다.
클라이언트에서 생성한 공개키를 서버에 복사하자.
여기서는 귀찮으니까 vi를 이용해서 클립보드에 옮겼다.
$ vi ~/.ssh/git.key.pub
cat으로 해도 되고, 파일을 서버로 복사해서 “>>” 명령을 이용해서 append시켜도 되니 취향대로 한다.
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAgEAyKnGRx/DsvDonZQxe4r39XOxlm5BLhx+ksjEubNNq1PWL5Z5XP/96xzf7PwY6C4SXKRc/vnrgqynL4qmcWbU/qXgEqazybTp76egttjRXI7NVKOXeh02pTI67MiEJYRTxcgwP1FS1YerVnBZb79odnAVZZ0utyGU6HZIWgnEk0YL8waygHZFke1PWN+clZedtGDjhO1CfcxmDWmiWWJFtJ/DJHo3nFGP8noQy+Fm/LWSyxwvFqsL6vLi1zftC4NqMfwbvUDNXfaRFjkRdfiq1rgn4Sx/48cs2KhH2utZh5Q21wzFYdEAFAnSlDKtZDmukx/WfcrLkid+yG53Vkv0RmGBe+k1pOaa97X6WFG+7vHhYRY8anQIDie4A56MDfwGRZi0eklxXfVn2dtOKnSXLZxCMucADHJwaT0xE9ANUq7Je+jgoONsCyyDWVpPOMEVF49t4DKbEJux7Ncir0jJ4sid3u4upjar7QNZHnOLEfiOHDoJ2km4+fXizwBqwnPytmkEjbiGuxpQrymQfbcEHsXFjNhRgFTE4u3PYpRyMxaSpE7dHrfH3ZLPSjFtAh39l6Whe2hds3oNr3VwwpRJERzQERhicu6oKHP8s9r2Qlhb4dwYbbLV1Q/TuV1PcMWXUz/Z3SuKelZ9czebkkFhfJXzDDaBNEj4+9i+h1jFXqk= weep@weeppp.com
내가 생성한 공개키이다.
일단 본인의 공개키를 잘 복사해둔다.
여기서부터가 진짜 서버설정이다.
서버의 git user 의 홈디렉토리로 이동한다.
$ cd /home/git
$ mkdir .ssh $ touch .ssh/authorized_keys
git홈에 .ssh 디렉토리를 만들고 공개키들을 저장하는 파일을 만든다.
이때 root로 작업했다면 소유자를 변경해주자.
$ chown -R git.git /home/git/.ssh
authorized_keys에 복사한 공개키를 넣으면 끝.
이제 클라이언트에서 git push나 git pull을 해보자
비밀번호를 묻지않으면 성공이다.