반응형

리눅스 공통 : ssh로 원격 명령어 실행

알게 된 배경

 서적을 통해서 쉘 스크립트를 통해서 파일 업로드 혹은 다운로드가 가능하다는 것을 알게 되었다. 특히 scp와 private와 public 키를 조합을 하여 자동 백업 등 여러 작업을 할 수 있다. 하지만, 종종 원격 디바이스(리눅스로 된)에 업로드된 파일등을 실행을 해야 할 경우에는 이러한 방법을 사용해야 한다.


 특히 다수의 서버에 프로그램을 테스트 할 경우에 이러한 방법을 적용할 수 있다면, 쉘 스크립트로 작성하여 자동화하는 것이 가능하게 된다.


명령어 전달 방법

방법은 의외로 간단하다 ssh 접속 방법에서 뒤에 명령어를 입력을 해주면 된다.


# 만약 rami 계정으로 192.168.0.2에 ls를 입력할 경우
ssh rami@192.168.0.2 ls



만약 명령어 이외에 옵션값도 전달을 해야한다면, ''이나 ""으로 명령어를 감싸면 된다.


# 만약 -al 옵션을 추가로 넣어야 할 경우
ssh rami@192.168.0.2 "ls -al"



 이제는 일괄로 ssh를 통해 명령어를 전달을 해야 한다면, 스크립트를 작성해서 진행하도록 하자.

 여기서 내 목적은 일괄적으로 각 서버에서 업로드한 프로그램의 make 명령어를 실행하는 것이었는데, make라는 명령어는 해당 폴더에 존재하는 파일명이 아니기 때문에 스크립트로 작성해서 실행하도록 했다. 일단 해결을 했지만, 더 좋은 방법이 있을 것 같다.



참조자료

해외 블로그

반응형

'리눅스 > 리눅스 공통' 카테고리의 다른 글

유닉스 : tar.gz 압축/해제 명령어  (0) 2017.09.29
반응형

Linux CentOS 7 : 방화벽 설정 입문

알게된 배경

 리눅스를 사용하는 대부분의 이유는 서버로 사용일 것이다. 그러면 항상 붙는 설정이 포트 설정과 방화벽 설정이다. 그래서 어쩔 수 없이 알아야 한다. 다만, 방화벽이 CentOS 7 으로 넘어와서 이전과 차이점이 있었다. 그래서 이전 버전이라면 추가 검색이 필요하다.


설정 커맨드

# tcp 방식 80포트 개방목록 추가
firewall-cmd --permanent --zone=public --add-port=80/tcp

# tcp 방식 80포트 개방목록 삭제
firewall-cmd --permanent --zone=public --remove-port=80/tcp

# 방화벽 재실행
firewall-cmd --reload


 아직 입문 수준이라 주로 사용하는게 위의 내용이 대부분이다. --이후에 붙는 내용들은 옵션이기 때문에 옵션 규칙만 맞는다면 순서는 상관없다.


주의 사항

 옵션 구분자'-'가 몇개인지 확인해야 한다. 종종 몇몇 블로그에서는 옵션 구분자를 하나로만 적는 경우가 있다. 방화벽에 대해 더 자세한 설명은 공식문서나 정리된 블로그를 참조하자.


참고자료

방화벽 공식 문서(영문)

한글로 일부 정리한 블로그

JAVA커뮤니티 글



반응형
반응형

리눅스 C : TCP 소켓 프로그램

알게된 배경

 라즈베리 파이를 위한 소캣 프로그램을 만들다 보니 어쩔 수 없이 TCP와 같은 소켓 프로그램을 제작하게 되었다. 소켓 프로그램의 경우 대부분 표준화가 되어 있으며, 구현하는 절차가 거의 정해져 있다. 때문에 이해를 했다 하더라도 외우고 있는건 무리기 때문에 기록을 남긴다.


사전에 염두 해야 할 점

 C와 C++이 일반적으로 빠른 이유는 운영체제와 거의 직접적으로 맞닿아서 작동이 된다는 점이다. 심지어 운영체제가 없는 마이크로프로세서 분야에서도 C가 사용되고 있다. 즉, 하드웨어나 운영체제의 영향을 많이 받기 때문에 당연히 윈도우와 리눅스간 코드는 차이가 있다.

 하나 더 알아야 할 것은 리눅스, OS X, FreeBSD 등 윈도우를 제외하고는 대부분은 유닉스 기반이라 소켓 코드가 거의 같다(게다가 컴파일러도 거의 비슷하다).


소스코드

 일반적으로 에코서버 코드가 기본이지만, 여기서는 스트림을 전송하거나 수신하는 코드는 제외한다.


서버

#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

void errorHandl(char* msg)
{
    puts(msg);
    exit(1);
}

int main(int argc, char* argv[])
{
    int serv_sock;
    int clnt_sock;
    struct sockaddr_in serv_addr;
    struct sockaddr_in clnt_addr;
    socklen_t clnt_addr_sz;

    if(argc != 2)
    {
        printf("Usage : %s <port>\n", argv[0]);
        exit(1);
    }
    // 서버 TCP 소켓 생성
    serv_sock = socket(PF_INET, SOCK_STREAM, 0);
    if(serv_sock == -1)
         errorHandl("socket() error");

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(atoi(argv[1]));

    if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
        errorHandl("bind() error");

    // serv_sock 다음 인수는 최대 대기중인 클라이언트 수
    if(listen(serv_sock, 5) == -1)
        errorHandl("listen() error");

    clnt_addr_sz = sizeof(clnt_addr);
    clnt_sock = accept(serv_sock, (struct sockaddr*) &clnt_addr, &clnt_addr_sz);
    if(clnt_sock == -1)
        errorHandl("accept() error");

    // 이제 소켓을 통해서 전송할 작업을 작성하면 된다.
    // 생략

    // 클라이언트/서버 순서대로 스트림을 닫느다.
    close(clnt_sock);
    close(serv_sock);

    return 0;
}


클라이언트

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

void errorHandl(char* msg)
{
    puts(msg);
    exit(1);
}

int main(int argc, char* argv[])
{
    int sock;
    struct sockaddr_in serv_addr;
    if(argc != 3)
    {
        printf("Usage : %s <IP> <port>\n", argv[0]);
        exit(1);
    }
    // TCP 소켓 설정
    sock = socket(PF_INET, SOCK_STREAM, 0);
    if(sock == -1)
         errorHandl("socket() error");

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
    serv_addr.sin_port = htons(atoi(argv[2]));

    if(connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
        errorHandl("connect() error");

    // 여기서 전송이나 수신하는 내용을 작성함
    // 생략

    // 소켓 스트림 닫음
    close(sock);

    return 0;
}



반응형
반응형

리눅스/윈도우 C : 현재날짜와 시간 가져오기

알게된 배경

 서버애서 생성하는 파일명에 날짜와 시간요소를 넣어서 생성하기 위해서 시스템의 시간을 알아야 할 필요가 있었다.


리눅스 계열(유닉스)과 윈도우

 윈도우 엄밀하게 말하면, MVC(VS 20xx)에서 사용하는 컴파일러는 C++에 대해서는 지원을 잘하지만, C에대해서는 지원이 잘 안되고 있다. 따라서 본의 아니게 소스코드를 실행할 때 차이점이 발생한다. 물론 이를 해결하기 위해서는 새로 소스코드를 작성하거나 minGW, Cygwin 처럼 리눅스 함수를 윈도우에 맞게 포팅해주는 컴파일러를 사용하면된다(하지만 socket 계열은 지원이 안되는 걸로 기억한다).

 시간에 대해서 더 자세히 알기 위해서는 struct tm에 대해서 검색을 해보도록 하자.



리눅스 소스코드

 C++에서는 헤더파일을 ctime으로 호출이 가능하며, 동일하게 사용이 가능하다.

// clock.c
#include <stdio.h>
#include <time.h>

void printTime(void)
{
    time_t timer;
    struct tm* t;

    timer = time(NULL);
    t = localtime(&timer);

    printf("UNIX Time : %d [sec]\n\n", timer);
    printf("year : %d\n", t->tm_year + 1900);
    printf("month : %d\n", t->tm_mon + 1);
    printf("days : %d\n", t->tm_mday);
    printf("hour : %d\n", t->tm_hour);
    printf("min : %d\n", t->tm_min);
    printf("sec : %d\n", t->tm_sec);
}


윈도우 소스코드

 리눅스 소스코드와 차이점은 struct tm 포인터 객체 대신 객체 자체를 선언하면 되며, localtime_s()를 사용한다.

// clock.c
#include <stdio.h>
#include <time.h>

void printTime(void)
{
    time_t timer;
    struct tm t;

    timer = time(NULL);
    localtime_s($t, &timer);

    printf("WINDOWS Time : %d [sec]\n\n", timer);
    printf("year : %d\n", t->tm_year + 1900);
    printf("month : %d\n", t->tm_mon + 1);
    printf("days : %d\n", t->tm_mday);
    printf("hour : %d\n", t->tm_hour);
    printf("min : %d\n", t->tm_min);
    printf("sec : %d\n", t->tm_sec);
}


참고자료

블로그: 유닉스 현재시간 아는 방법 소개


반응형

'C' 카테고리의 다른 글

리눅스 C : TCP 소켓 프로그램  (0) 2017.05.24
Linux C : 파일이나 폴더 조회하기  (0) 2017.04.24
C : 구조체를 네임스페이스처럼 사용하기  (0) 2017.04.22
C : 문자열 숫자 변환  (0) 2017.04.21
C : extern 키워드  (0) 2016.11.28
반응형

Linux CentOS 7 : root 계정 직접 로그인 막기

알게된 배경

 ssh 원격을 사용하면서, root 계정으로 직접적으로 로그인이 가능하게 할 경우 비밀번호에 대해서 상당한 취약점이 발생한다는 것을 알게 되었기 때문에 이러한 취약점을 보강하기 위해서 root 계정의 직접 로그인을 막는다.


설정 변경 방법

 설정파일을 변경하고 리부트를 하면 된다.

vi /etc/ssh/sshd_config

이 파일에서 아래의 #PermitRootLogin yes 부분을 찾아서 주석(#)을 해제한 다음에 yes를 no로 바꾸면 된다.

#PermitRootLogin yes

 vi가 익숙하지 않다면, 익숙한 편집기를 사용해도 된다. 

 vi에서는 '/'키를 눌러서 'PermitRootLogin'으로 검색을 하면 쉽게 찾을 수 있다. 찾았으면, 'i'를 눌러서 편집모드로 바꾼뒤 주석해제와 yes를 no로 바꾼뒤 'esc'로 편집모드를 나온다음에 ':wq' 입력하여 저장하고 vi를 닫는다.

 이후 리부트 하면 root 계정으로 바로 로그인이 안되고 다른 계정을 통해서 로그인한뒤에 'su'명령어를 통해서 root 계정으로 전환할 수 있다.

반응형
반응형

Linux CentOS 7 : 고정IP 설정

알게된 배경

 서버를 구축하고 사용하려 하다 보면 IP관리를 위해서 고정 IP는 필수로 설정하게 된다. 가장 이상적인 방법은 CentOS7부터는 설치할때 GUI에서 설정할 수 있으니 가능하면 이때 설치를 해놓으면 좋다. 하지만, 관리하다 보면 변동 사항이 있을 수도 있으니 정리해 놓자


고정 IP 설정 파일 위치

cd /etc/sysconfig/network-scripts
vi ifcfg-eth0

vi 사용법을 모른다면, 다른 편집기를 사용해도 된다.

 여기서 파일은 과거에는 ifcfg-eth0이지만, 설치할때 디바이스를 뭘로 잡았느냐에 따라서 ifcfg-뒤의 이름이 다르다. 때문에 ls를 입력하여 어떤 파일이 있는지 확인해야 한다. wlan0 같은 이름을 가진 파일은 와이파이 디바이스니 설치할때 뭘로 했었는지 기억을 떠올리던가 기록을 해둔것을 찾아서 수정해야 한다.


 대략 많은 내용의 설정파일들이 다음의 내용을 수정하고 없으면, 추가를 해서 작성하면 된다.

BOOTPROTO=static
IPADDR=XXX.XXX.XXX.XXX
NETMASK=XXX.XXX.XXX.XXX
DNS2=XXX.XXX.XXX.XXX
GATEWAY=XXX.XXX.XXX.XXX
DNS1=XXX.XXX.XXX.XXX

 수정이 끝났으면, vi의 경우 저장하고 종료한다음에 리부트(reboot)하거나 디바이스를 재시작 해주면 된다.


각 필요한 항목에 대한 설명은 다음과 같다.


 BOOTPROTO

 static이면 고정, dhcp이면 유동(자동), none이면 사용안함

 IPADDR

 고정(사용)할 IP주소 

 NETMASK

 네트워크 제공쪽 넷마스크(공유기의 내부망 정보 참조)

 국민 공유기인 iptime 제품 경우 255.255.255.0 이 기본 설정이다.

 DNS2

 보조DNS 서버(공유기 혹은 모뎀에서 확인가능)

 GATEWAY

 네트워크 제공자(공유기 혹은 모뎀)

 DNS1

 DNS 서버(공유기 혹은 모뎀에서 확인가능)


나머지는 네트워크 디바이스에 관한내용이기 때문에 다음에 다루던가 네트워크 쟁이들에게 물어보자.


참조 자료

고정IP 설정 메모된 블로그


반응형

+ Recent posts