프로세스 감시 및 매니져 프로그램을 제작 중입니다.

toughguy의 이미지

안녕하세요,
외부에서 linux server내의 프로세스를 감시 및 관리하려는 프로그램을 만들고 있습니다.

Client는 Html + Php 로 구현되어 있구요,
감시 및 관리하는 server 는 C++로 만드는 중입니다.

Client는 관리 server에게 어느 특정 프로그램을 Start 및 Stop 을 요청 할 수 있는데,
Stop은 잘 되는데, Start 했을 경우가 문제 입니다.

프로그램 Start 했을 경우, 관리 Server내에선

Start.sh를 실행 하게 됩니다. Start.sh는 관리 프로그램의 fulpath에 & 를 더해 돌리게 되구요,.

근데 프로그램을 시작 하고, 모니터링 서버를 내린후 다시 시작하면, 모니터링 서버를
다시 시작 할 수 없습니다.(bind Error)

그래서 좀전에 시작했던 프로그램을 죽이고 시작하면, 모니터링 서버가 시작이 가능해 집니다.

어떻게 해야 해결 할 수 있을까요,

프로그램은 현재 test용으로 아무 내용없이 while 안에 sleep 만 있는 상태 입니다.

gala의 이미지

귀찬아서 차일 피일 미루고 있네요 ....
웹으로 말고 APP 로 소켓통신 해서 만들려고 하는데..
언제쯤 시작할지...참고할 레퍼런스 가지고 계시면 부탁 드릴게요.

neomark의 이미지

얼핏 떠오르는건 address already in use 군요.

근대 프로그램을 죽이고 하면 시작 가능하다니 좀 의외네요.

하등의 상관 관계가 없지 않나요?

살리고 띄우는건 서로 다른 프로세스가 아닌가 해서요( shell script, fork, system, exec 등으로 말이죠)

bind는 network에러이니...

좀더 정확한 에러메시지가 필요할듯 합니다.

지금 저의 추측으로는 기존에 떠 있는 프로그램과는 별도로 데몬프로세스를 재 시작하는 시점에 문제가 있지 않나 싶습니다.

만일 address already in use 라면 server내의 socket에 재사용 가능한 flag(SO_REUSEADDR)를 통해 해결하실 수 있습니다.

seank76의 이미지

neomark님의 말씀이 맞지않나싶네요.

기존에 떠 있는 프로그램이 (또는 Start.sh가) daemon으로 남겨져서 모니터링 프로그램의 종료를 막는게 아닌지요.

모니터링 프로그램을 내린 후 ps로 그 프로그램이 진짜로 죽었는지 확인해보세요.

toughguy의 이미지

우선 seank76님과 neomark 님 감사합니다.

모니터링 프로그램을 띄우고, Client가 프로그램을 Start 후, 모니터링 프로그램을 종료 한뒤,
ps 로 프로세스 확인 결과,
start.sh는 없지만, 모니터링 프로그램이 Start 했던 프로그램은 살아 있습니다.

Bind 에러는 port가 문제 있는거 같아,
port 확인해보니, 모니터링 프로그램이 사용해야하는 포트가 Close_Wait 상태에 있군요,
계속해서 Close_Wait상태(1시간 이상) 이여서
아까 Client가 실행 했던 프로그램을 kill 하고, 모니터링 프로그램을 실행하니, 시작이 됩니다.

SO_REUSEADDR 옵션은 켜둔 상태구요,

모니터링 프로그램 내부에선, 새로운 프로그램을 시작할때, pid 를 Fork 하지 않고, system을 통해 쉘 스크립트(start.sh)를
실행합니다.

아무리 생각해도 모니터링 프로그램이 죽였을경우, 왜 재시작이 안되는지 모르겠네요 ㅠㅠ

도와주세요~

neomark의 이미지

system 함수는 내부적으로 /bin/sh -c 를 통해서 프로그램을 실행시킨다고 man page에 나오는군요.

말씀하신대로 Start.sh에는 프로그램을 backgrond로 돌려놓았으니 일단 system에서 block 당할일은 없겠지만,

저 shell이란 놈이 문제가 되는 듯 합니다.

즉 sh도 프로그램을 실행시킬 때는 내부적으로 fork를 사용하는 것으로 알고 있습니다.( 100프로 정확하다고는 말씀 못드리겠습니다..

직접 본게 아니라서 -.-;;)

즉, Start.sh가 호출되는 시점에서는 아무것도 하지 않고 sleep만 있는 프로그램은 이미 fork를 통해 생성된 놈이기 때문에

parent process(monitor daemon)의 환경(?)을 그대로 물려 받는거죠. 즉, file descriptor 라던지 socket 이라던지 말이죠...

제가 간단히 test 해보니 정확히 child process( Start.sh로 실행된 프로그램)이 종료되는 시점에 CLOSE_WAIT가 풀리네요.

정리하자면 system 함수에서 프로그램을 실행시키면 /bin/sh로 실행되는데 이놈이 결국 fork를호출하게 되어 daemon process에서

열어놓았던 port를 고대로 물려 받는다는 겁니다. 따라서 daemon을 재시작 하려고 해도 child process가 port를 잡고 있기 때문에

address already in use가 나는 것이죠.

해결방법은 ...

아마도 socket을 닫을 때 close를 쓰신듯 한데...

child process에서 parent로 부터 받은 port를 쓸 일이 없다면( 아마도 지금껏 읽어본봐로는 daemon과는 상관없는 프로그램들로 보입니다.)

close대신 shutdown을 사용하십시요.

close와 shutdown의 차이는 close는 해당 프로세스에서만 종료(닫기)를 하는 것이고,

shutdown은 그 port를 공유하는 모든 프로세스에서 종료(닫기)를 하는 것입니다.

close 대신 shutdown을 사용하면 TIME_WAIT는 걸리지만, daemon을 재시작 하는데는 문제가 없습니다.

이런 류(?)의 프로그램을 작성하실 때는 저 connection의 연결과 끊어짐을 잘 관리해주셔야 할겁니다.

ps. 참고로, 최초 단말 client를 위해 open한 socket을 shutdown하지 않고 close 할경우에는 재밌는 경우가 생기는군요. Start.sh로 실행한

프로그램이 있기 때문에 한쪽에선 CLOSE_WAIT가 걸림과 동시에 그 프로세스가 살아있기 때문에 처음에열었던 port도 계속 listen 상태로 나오네요

daemon의 자가복제랄까... -.-a ;;;

neomark의 이미지

말씀드린다면..

shutdown을 쓰면 daemon의 재시작 문제는 해결하실 수 있습니다만, 문제는 그렇게 구동한 프로세스들이 daemon 프로세스의

port들을 모두 가지고 있다는 문제가 생길 수 있죠... 프로세스가 모두 대몬들이라면 나중에는 too many open files가 날 수도 있습니다.

system()함수 말고 fork후에 exec* 등으로 좀더 명확히 문제를 해결하셔야 할듯 하네요.

IsExist의 이미지

system() 함수의 man 페이지를 보면 system() 함수내에서 fork을 한뒤 자식 프로세스로 sh -c 을
exec 한다고 나옵니다. 그리고 그 프로그램이 끝나기를 wait 합니다. 따라서 system() 함수
호출이 종료될때까지 모니터링 서버는 block 된 상태라고 봐야 겠네요(따로 fork 함수로 분기를
만들지 않는다고 본문에서 얘기하는걸로 봐서는요).

모니터링 서버가 클라이언트 요청을 start.sh 을 실행하고 동시에 다른 요청을 기다리는
구현으로 할려고 하는건지 아니면 start.sh가 끝나기를 기다렸다가 다음 요청을 처리하는
식으로 할려고 하는 건가요?

모니터링 프로그램(서버 맞죠?)가 재시작이 안된다는 어떤 의미 인가요? 모니터링 프로그램이
죽은 다음 수동으로 실행을 시키는걸 말하는 거죠? 앞에서 SO_REUSEADDR 을 제대로
사용했다면 문제가 없을듯 한데요.. 일단 오류가 나는 부분에서 에러를 다 출력하게
해보세요. errno 값 말입니다. strerror() 함수를 써두 되구요. perror() 함수를
써두 되구요.
---------
간디가 말한 우리를 파괴시키는 7가지 요소

첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스

이익추구를 위해서라면..

다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치

---------
간디가 말한 우리를 파괴시키는 7가지 요소

첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스

이익추구를 위해서라면..

다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치

toughguy의 이미지

neomark 님 IsExist 님 답변 감사드립니다~
우선 shutdown으로 문제를 해결해 보려 합니다.
system 명령어 자체도 fork 후 exec를 하는 것이니, fork후 exec를 하는 방법으론 해결 되지 않을 듯 하네요,

답변 정말 감사드립니다^^

neomark의 이미지

프로그램 내에서 fork를 사용한다면 해결 가능하지 않나요??

system함수 호출은 system()함수 내부적으로 fork가 일어나서 어쩔 수 없지만,

daemon에서 fork를 한다면 child process일 경우 socket들을 닫아 줄 수 있을거 같은데요...

socket을 닫은 다음 exec* 를 하시면 될듯한데....

어쨌든 잘 해결하시길 바랍니다.

^^

vinus의 이미지

neomark 님 말씀에 동감 입니다.
close()를 적절히 이용하셔서 open된 socket을 닫으셔야 겠네요.

Start.sh를 실행하시기전. 즉 fork()이후에 소켓을 닫으시면 되지 않알까요.

>>>행복한 웃음<<<

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.