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

2010년 12월 29일 수요일

upstart 를 이용해서 daemon 죽었을때 다시 띄우기

http://upstart.ubuntu.com/

서버등을 돌리다가 죽는경우 다시 띄우거나 하는 작업이 필요한데 개발중에는 repeat.sh 등을 만들어서 쓰고 있지만 데모용으로 띄울경우는 init 등에서의 작업이 필요. ubuntu 가 가진 upstart 를 쓸때의 간단한 사용법을 적어둔다.

  1. /tmp/a.out 에 데몬이 있다고 가정해보자.
  2. /etc/init/foo.conf 작성
    description "shit"
    exec /tmp/a.out
    respawn
  3. sudo initctl reload-configuration 으로 foo.conf 읽고
  4. sudo start foo 로 프로세스 돌리고
  5. initctl status foo 로 확인
  6. sudo stop foo 로 프로세스 정지
좀더 상세한 사항은 init(5), initctl 등의 manpage 참고

2010년 12월 17일 금요일

ulimit 값 변경해주기

리눅스 설치때마다 한번씩 해주는 작업이라 항상 가물가물하다.
이번에 적어두자.

http://posidev.com/blog/2009/06/04/set-ulimit-parameters-on-ubuntu/ 가 원문.

  1. /etc/security/limits.conf 에 적당히 내용 추가
    yoonkn           soft    nofile          20000       
    yoonkn           hard    nofile          65000
    yoonkn           soft    core            100000
    yoonkn           hard    core            100000
  2. /etc/pam.d/common-session 에 아래 내용 추가
    session required pam_limits.so
  3. reboot



2009년 6월 8일 월요일

windows 로...

이번에 하게 된 일이 윈도에서만 개발환경이 세팅되는지라 오랜만에 윈도로 부팅을 하고 이것저것 세팅을 해줬다. 여러가지 어플리케이션 버전 올려주고 사전프로그램으로 stardict 에서 lingoes 로 갈아타고 ssh 접속이 어려워졌으니 집과 파일싱크를 위해서 dropbox 를 설치하고 등등

음 역시나 UI 반응은 윈도가 좀더 빠릿한 편.
윈도쪽은 클래식 스타일을 쓰고있고 리눅스에선 메타시티를 쓰기때문에 그다지 공평한 비교는 아니지만... UI 반응이나 특히나 firefox 속도등 데탑으로 쓰기엔 윈도가 더 좋다.

그런데 워낙 오랜만이라 emacs 세팅이 좀 안맞는 부분들이 좀 생겨서 삽질좀 해야 쓰겠구만.

2009년 2월 19일 목요일

netcat

으음.
netcat.. 존재를 알고는 있지만 막상 필요할때는 항상 까먹어서 걍 스크립트질하기 때문에 지금껏 써본적이 없는 놈. socat 은 처음알았네.

기억해두고 다음엔 좀 써먹어보자.

2008년 10월 7일 화요일

SO_KEEPALIVE tcp 연결유지

http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/

tcp 연결의 경우 접속이 끊어진걸 알지 못하는 경우가 있다. 특히나 트래픽이 적은 경우 문제가 된다. 이런 문제때문에 접속유지용으로 별 의미없는 내용을 주고 받는 식으로 구현을 해왔는데 (heartbeat/ping) 마침 시간이 나서 SO_KEEPALIVE 문서를 읽어봤다....

...읽어보고 그냥 지금까지 하던대로 핑퐁 주고받는식으로 짜기로 했지만 읽어둔것 대강 정리만 해둔다.

  • SO_KEEPALIVE 옵션을 켜두면 적절한 시간마다 0 length data 에 ACK 를 켜서 쏜다. 상대방은 굳이 KEEPALIVE 지원이 필요 없다. 길이가 0 라서 스트림식으로 도는 tcp 코드는 수정이 필요없다. 완존 투명.
  • 이때 사용되는 커널변수들은 세가지로 모두 /proc/sys/net/ipv4/ 에서 확인가능
    • tcp_keepalive_time
    • tcp_keepalive_intvl
    • tcp_keepalive_probes
  • 시스템레벨에서 위값을 바꾸는 방법도 소개되어있는데 이건 내 관심밖
  • 프로그램레벨에서 바꿔주려면 setsockopt 로 SOL_TCP 레벨에서 아래 세값이 각각 위의 값에 대응한다.(참고로 SO_KEEPALIVE 는 SOL_SOCKET 레벨이지. 사실 SOL_TCP 레벨값을 수정해본적은 지금껏 없었다..)
    • TCP_KEEPIDLE
    • TCP_KEEPINTVL
    • TCP_KEEPCNT
  • 문서상에서는 위 세가지 값이 시스템전체를 바꾸는게 아니고 해당 소켓에만 적용된다고 한다. 좋군. 그런데 이게 리눅스 외의 다른 OS 들에서도 사용할수 있는 방법인지 확인해보지는 못했다. 만약 이방법을 쓰고자 한다면 반드시 확인해봐야겠지.
  • 코드수정이 어려운경우엔 libkeepalive 라는걸 사용하는 방법도 있다.

SO_KEEPALIVE 를 쓰지 않기로 한 이유는.. ping/pong 구조 구현이 그다지 어렵지 않고 후에 필요하다면 서버쪽에서만 SO_KEEPALIVE 구현을 추가할수 있기 때문에 ping 방식이 문제가 생기더라도 투명하게 수정이 가능하다는점때문.


2009/02/13 추가.
결국 오늘 KEEPALIVE 구현을 추가했다.
SOL_TCP 값이 inet/tcp.h 에 들어있더라.






2008년 9월 24일 수요일

linux 에서 특정 인터페이스 카드의 상태 읽어오기

MAC 어드레스 얻는것과 마찬가지로 걍 ioctl 쓰는건데.. 역시 샘플로 만들어둔 코드 그냥 지우기 뭐해서 적어둔다. 랜선이 껴진 상태인지 판단하기 위해서 만든 코드인데 현재 내 PC 네트웍을 죽일수가 없어서 아직 테스트는 안해봤다.

내일 출근하면 랜선 뺐다 껴보고, 인터페이스 올리고 내리고 등등 하면서 플래그값 변화를 체크해보자.



#include <sys/socket.h>
#include <sys/types.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static void show_ifr_flags(unsigned int flags);

int main()
{
/* 인터페이스 이름을 eth0 으로 고정했는데 시스템 내의
* 인터페이스들을 얻어오려면 SIOCGIFCONF 참고
*/
const char* ifname = "eth0";

struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);

int s = socket(PF_INET, SOCK_STREAM, 0);
if(s<0) perror("socket failed"); /* TODO 더 나은 에러처리 */
int r = ioctl(s, SIOCGIFFLAGS, &ifr);
if(r<0) perror("ioctl failed"); /* TODO 더 나은 에러처리 */

show_ifr_flags(ifr.ifr_flags);

close(s);
}

/* 내 시스템에서 net/if.h 를 보면 이 flag 의 타입으로 unsigned short 가
* 쓰였다. 환경마다 다를것 같기도 헌데..
*/
void show_ifr_flags(unsigned int flags)
{
#define SHOW_FLAG(flag, desc) printf("%-16s = %d // %s\n", #flag, (flags&flag)!=0, desc);
SHOW_FLAG(IFF_UP, "Interface is up");
SHOW_FLAG(IFF_BROADCAST, "Broadcast address valid");
SHOW_FLAG(IFF_DEBUG, "Turn on debugging");
SHOW_FLAG(IFF_LOOPBACK, "Is a loopback net");
SHOW_FLAG(IFF_POINTOPOINT, "Interface is point-to-point link");
SHOW_FLAG(IFF_NOTRAILERS, "Avoid use of trailers");
SHOW_FLAG(IFF_RUNNING, "Resources allocated");
SHOW_FLAG(IFF_NOARP, "No address resolution protocol");
SHOW_FLAG(IFF_PROMISC, "Receive all packets");
SHOW_FLAG(IFF_ALLMULTI, "Receive all multicast packets");
SHOW_FLAG(IFF_MASTER, "Master of a load balancer");
SHOW_FLAG(IFF_SLAVE, "Slave of a load balancer");
SHOW_FLAG(IFF_MULTICAST, "Supports multicast");
SHOW_FLAG(IFF_PORTSEL, "Can set media type");
SHOW_FLAG(IFF_AUTOMEDIA, "Auto media select active");
SHOW_FLAG(IFF_DYNAMIC, "Dialup device with changing addresses");
#undef SHOW_FLAG
}


음.. 돌려보고 결과를 적어둔다.

각 상황별 결과 보기


정리하자면
랜선끼고 ifup
IFF_UP = 1 // Interface is up
IFF_RUNNING = 1 // Resources allocated

랜선끼고 ifdown
IFF_UP = 0 // Interface is up
IFF_RUNNING = 0 // Resources allocated

랜선뽑고 ifup
IFF_UP = 1 // Interface is up
IFF_RUNNING = 0 // Resources allocated

랜선뽑고 ifdown
IFF_UP = 0 // Interface is up
IFF_RUNNING = 0 // Resources allocated


linux 에서 특정 인터페이스 카드의 MAC 어드레스 읽어오기

갑자기 이런 코드가 필요해져서 짜봤다.
샘플수준의 코드



/*
eth0 인터페이스의 하드웨어 어드레스(mac) 을 찍어주는 코드

1. 인터페이스 이름은 eth0 라고 가정했다. 런타임에 알아내야 한다면
SIOCGIFCONF 등을 참고

2. 소켓하나가 필요. 다른 예제들을 보니 보통 DGRAM 으로
만드네.. STREAM 으로도 동작엔 문제가 없는듯 한데 DGRAM 이 쓰이는
이유가 뭘까

3. ifreq 구조체 만들어서 적절히 채우고

4. ioctl 콜

5. SIOCGIFHWADDR 를 요청했다면 결과는 ifreq 구조체의
ifr_hwaddr.sa_data 를 6 바이트 읽어내면 된다.
*/
#include <sys/socket.h>
#include <sys/types.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
const char* ifname = "eth0";

int s = socket(AF_INET, SOCK_DGRAM, 0);
if(s < 0) perror("socket fail"); /* TODO 에러처리 */

struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);

if(ioctl(s, SIOCGIFHWADDR, &ifr) < 0)
perror("ioctl fail"); /* TODO 에러처리 */

const unsigned char* mac = ifr.ifr_hwaddr.sa_data;
printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0],
mac[1],
mac[2],
mac[3],
mac[4],
mac[5]);

close(s);
}


음. 추가로 SIOCGIFADDR 로 ip 얻어오는 함수도 만들어봤다. ioctl 쪽은 정말 드럽다. sockaddr_in 때문에 헤더파일 몇개 추가해야 한다는것 잊지 말도록. man inet_ntoa 참고

int get_ip_address(char* ip, int iplen, const char* ifname)
{
int s;
struct ifreq ifr;
struct sockaddr_in* sin;

s = socket(AF_INET, SOCK_DGRAM, 0);
if(s<0) return -1;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);

if(ioctl(s, SIOCGIFADDR, &ifr) < 0)
{
close(s);
return -1;
}

sin = (struct sockaddr_in*)&ifr.ifr_addr;
strncpy(ip,
inet_ntoa(sin->sin_addr),
iplen);

close(s);
return 0;
}