2007/12/26 22:51

PHP RRDTool tutorial

http://www.ioncannon.net/system-administration/59/php-rrdtool-tutorial/

On a number of occasions I've used RRDTool to graph network traffic and the like. A few years ago when I started using cacti I started wondering how to make the graphs myself. Creating the graphs on the command line isn't that hard once you know how to set things up and it turns out doing the same in PHP is just as easy.

For this tutorial I'm going to assume you understand how to get RRDTool installed and working from the command line. If not you should take a look at this tutorial (if you are in a hurry look at the "A Real World Example" section) or any of the tutorials on this page.

Setup and introduction

You need to have PHP compiled with RRDTool support to run the following PHP examples. If you compile PHP by hand then see: how to build the php rrdtool extension by hand. If you are using a distribution's pre-compiled PHP binary you should be able to install a second package with RRDTool support. You can verify that your PHP install is ready to go by running this:

<?php
phpinfo(INFO_MODULES);
?>

Then search for "rrdtool" in the output and make sure that "rrdtool support" is enabled.

While going through each of the following steps you will notice that each call takes a couple of parameters and then one parameter that is just a string of options. The string of options is exactly how it is for generating/updating/graphing RRDs from the command line. This makes for a consistent interface for the different languages that have RRDTool support.

Creating a RRD

We first need to create a database for our data. For these examples I will be creating a database that could be used for generating network graphs. This database is created for updates every 5 minutes (300 seconds), has input and output counters that store data for the average and max counts and stores enough samples for hourly, daily, monthly and yearly graphs of both average and max.

<?php

  $fname = "net.rrd";

  $opts = array( "--step", "300", "--start", 0,
           "DS:input:COUNTER:600:U:U",
           "DS:output:COUNTER:600:U:U",
           "RRA:AVERAGE:0.5:1:600",
           "RRA:AVERAGE:0.5:6:700",
           "RRA:AVERAGE:0.5:24:775",
           "RRA:AVERAGE:0.5:288:797",
           "RRA:MAX:0.5:1:600",
           "RRA:MAX:0.5:6:700",
           "RRA:MAX:0.5:24:775",
           "RRA:MAX:0.5:288:797"
        );

  $ret = rrd_create($fname, $opts, count($opts));

  if( $ret == 0 )
  {
    $err = rrd_error();
    echo "Create error: $err\n";
  }
?>

After running you will have a file called net.rrd in the current directory. This is your RRD and will contain all the samples for your graphs.

For more information on the options to rrd_create see: rrdcreate

Updating a RRD

The next step is to update your RRD on the frequency you set when you created it. In the case above the frequency was set to 5 minutes (300 seconds). The following script generates random input and output values as input to the update function, sleeps for 300 seconds and then loops.

<?php

  $fname = "net.rrd";

  $total_input_traffic = 0;
  $total_output_traffic = 0;

  while(true)
  {
    $total_input_traffic += rand(10000, 15000);
    $total_output_traffic += rand(10000, 30000);

    echo time() . ": " . $total_input_traffic . " and " . $total_output_traffic . "\n";

    $ret = rrd_update($fname, "N:$total_input_traffic:$total_output_traffic");

    if( $ret == 0 )
    {
      $err = rrd_error();
      echo "ERROR occurred: $err\n";
    }

    sleep(300);
  }
?>

Your input and output values could be pulled from anywhere here, I just wanted to have a source that would work for anyone who wanted to try the script.

After letting this script run for a few hours you can run the following shell script to see what type of data you have collected so far:

For more information on the options to rrd_update here: rrdupdate

#!/bin/sh
END=`date +%s`
START=`echo $END-3600|bc` # over the hour
rrdtool fetch net.rrd AVERAGE --start $START --end $END

That should display the average sample values for the last hour.

Displaying RRD data as a graph

Now that you have data in your RRD you will want to graph it. The following code will graph the average input and output for 1 day as well as the max for that day.

<?php

  $opts = array( "--start", "-1d", "--vertical-label=B/s",
                 "DEF:inoctets=net.rrd:input:AVERAGE",
                 "DEF:outoctets=net.rrd:output:AVERAGE",
                 "AREA:inoctets#00FF00:In traffic",
                 "LINE1:outoctets#0000FF:Out traffic\\r",
                 "CDEF:inbits=inoctets,8,*",
                 "CDEF:outbits=outoctets,8,*",
                 "COMMENT:\\n",
                 "GPRINT:inbits:AVERAGE:Avg In traffic\: %6.2lf %Sbps",
                 "COMMENT:  ",
                 "GPRINT:inbits:MAX:Max In traffic\: %6.2lf %Sbps\\r",
                 "GPRINT:outbits:AVERAGE:Avg Out traffic\: %6.2lf %Sbps",
                 "COMMENT: ",
                 "GPRINT:outbits:MAX:Max Out traffic\: %6.2lf %Sbps\\r"
               );

  $ret = rrd_graph("net_1d.gif", $opts, count($opts));

  if( !is_array($ret) )
  {
    $err = rrd_error();
    echo "rrd_graph() ERROR: $err\n";
  }
?>

You should end up with a file named net_1d.gif in your working directory that looks something like:

You can also do weekly and monthly graphs by changing the start parameter to -1w or -1m:




For the impatient you can download my net.rrd file and try the graphs for yourself.

See the other tutorials for more information on the options you have for graphing.

For more information on the options to rrd_graph see: rrdgraph

Trackback 0 Comment 0
2007/11/21 01:53

자바스크립트에서 스트링관련해서 자주 쓰이는 함수들

출처: http://www.zzbb.kr/24




자바스크립트에서 스트링관련해서 자주 쓰이는 함수들을 정리해 놓은 포스트가 있어 소개합니다.
이정도면 유용하게 활용할수 있을것 같네요.


    1
 /*--------------------------------------------------------------------------------*\

    2  *  JavaScript framework, version 2.0

    3  *

    4  *  Date : 2006. 08. 15.

    5  *  Copyright 1998-2007 by Vricks Studio All right reserved.

    6  *  @author Jeff Yang routine@vricks.com

    7  *  자주 쓰이는 스트링 관련 prototype관련 정리

    8 \*--------------------------------------------------------------------------------*/

    9 

   10 /*--------------------------------------------------------------------------------*\

   11  *  String prototype

   12 \*--------------------------------------------------------------------------------*/

   13     //-----------------------------------------------------------------------------

   14     // 문자의 좌, 우 공백 제거

   15     // @return : String

   16     //-----------------------------------------------------------------------------

   17     String.prototype.trim = function() {

   18         return this.replace(/(^\s*)|(\s*$)/g, "");

   19     }

   20     //-----------------------------------------------------------------------------

   21     // 문자의 좌 공백 제거

   22     // @return : String

   23     //-----------------------------------------------------------------------------

   24     String.prototype.ltrim = function() {

   25         return this.replace(/(^\s*)/, "");

   26     }

   27     //-----------------------------------------------------------------------------

   28     // 문자의 우 공백 제거

   29     // @return : String

   30     //-----------------------------------------------------------------------------

   31     String.prototype.rtrim = function() {

   32         return this.replace(/(\s*$)/, "");   

   33     }

   34     //-----------------------------------------------------------------------------

   35     // 문자열의 byte 길이 반환

   36     // @return : int

   37     //-----------------------------------------------------------------------------

   38     String.prototype.byte = function() {

   39         var cnt = 0;

   40         for (var i = 0; i < this.length; i++) {

   41             if (this.charCodeAt(i) > 127)

   42                 cnt += 2;

   43             else

   44                 cnt++;

   45         }

   46         return cnt;

   47     }

   48     //-----------------------------------------------------------------------------

   49     // 정수형으로 변환

   50     // @return : String

   51     //-----------------------------------------------------------------------------

   52     String.prototype.int = function() {

   53         if(!isNaN(this)) {

   54             return parseInt(this);

   55         }

   56         else {

   57             return null;   

   58         }

   59     }

   60     //-----------------------------------------------------------------------------

   61     // 숫자만 가져 오기

   62     // @return : String

   63     //-----------------------------------------------------------------------------

   64     String.prototype.num = function() {

   65         return (this.trim().replace(/[^0-9]/g, ""));

   66     }

   67     //-----------------------------------------------------------------------------

   68     // 숫자에 3자리마다 , 를 찍어서 반환

   69     // @return : String

   70     //-----------------------------------------------------------------------------

   71     String.prototype.money = function() {

   72         var num = this.trim();

   73         while((/(-?[0-9]+)([0-9]{3})/).test(num)) {

   74             num = num.replace((/(-?[0-9]+)([0-9]{3})/), "$1,$2");

   75         }

   76         return num;

   77     }

   78     //-----------------------------------------------------------------------------

   79     // 숫자의 자리수(cnt)에 맞도록 반환

   80     // @return : String

   81     //-----------------------------------------------------------------------------

   82     String.prototype.digits = function(cnt) {

   83         var digit = "";

   84         if (this.length < cnt) {

   85             for(var i = 0; i < cnt - this.length; i++) {

   86                 digit += "0";

   87             }

   88         }

   89         return digit + this;

   90     }

   91     //-----------------------------------------------------------------------------

   92     // " -> &#34; ' -> &#39;로 바꾸어서 반환

   93     // @return : String

   94     //-----------------------------------------------------------------------------

   95     String.prototype.quota = function() {

   96         return this.replace(/"/g, "&#34;").replace(/'/g, "&#39;");

   97     }

   98     //-----------------------------------------------------------------------------

   99     // 파일 확장자만 가져오기

  100     // @return : String

  101     //-----------------------------------------------------------------------------

  102     String.prototype.ext = function() {

  103         return (this.indexOf(".") < 0) ? "" : this.substring(this.lastIndexOf(".") + 1, this.length);   

  104     }

  105     //-----------------------------------------------------------------------------

  106     // URL에서 파라메터 제거한 순수한 url 얻기

  107     // @return : String

  108     //-----------------------------------------------------------------------------   

  109     String.prototype.uri = function() {

  110         var arr = this.split("?");

  111         arr = arr[0].split("#");

  112         return arr[0];   

  113     }

  114 

  115 /*---------------------------------------------------------------------------------*\

  116  *  각종 체크 함수들

  117 \*---------------------------------------------------------------------------------*/

  118     //-----------------------------------------------------------------------------

  119     // 정규식에 쓰이는 특수문자를 찾아서 이스케이프 한다.

  120     // @return : String

  121     //-----------------------------------------------------------------------------

  122     String.prototype.meta = function() {

  123         var str = this;

  124         var result = ""

  125         for(var i = 0; i < str.length; i++) {

  126             if((/([\$\(\)\*\+\.\[\]\?\\\^\{\}\|]{1})/).test(str.charAt(i))) {

  127                 result += str.charAt(i).replace((/([\$\(\)\*\+\.\[\]\?\\\^\{\}\|]{1})/), "\\$1");

  128             }

  129             else {

  130                 result += str.charAt(i);

  131             }

  132         }

  133         return result;

  134     }

  135     //-----------------------------------------------------------------------------

  136     // 정규식에 쓰이는 특수문자를 찾아서 이스케이프 한다.

  137     // @return : String

  138     //-----------------------------------------------------------------------------

  139     String.prototype.remove = function(pattern) {

  140         return (pattern == null) ? this : eval("this.replace(/[" + pattern.meta() + "]/g, \"\")");

  141     }

  142     //-----------------------------------------------------------------------------

  143     // 최소 최대 길이인지 검증

  144     // str.isLength(min [,max])

  145     // @return : boolean

  146     //-----------------------------------------------------------------------------

  147     String.prototype.isLength = function() {

  148         var min = arguments[0];

  149         var max = arguments[1] ? arguments[1] : null;

  150         var success = true;

  151         if(this.length < min) {

  152             success = false;

  153         }

  154         if(max && this.length > max) {

  155             success = false;

  156         }

  157         return success;

  158     }

  159     //-----------------------------------------------------------------------------

  160     // 최소 최대 바이트인지 검증

  161     // str.isByteLength(min [,max])

  162     // @return : boolean

  163     //-----------------------------------------------------------------------------

  164     String.prototype.isByteLength = function() {

  165         var min = arguments[0];

  166         var max = arguments[1] ? arguments[1] : null;

  167         var success = true;

  168         if(this.byte() < min) {

  169             success = false;

  170         }

  171         if(max && this.byte() > max) {

  172             success = false;

  173         }

  174         return success;

  175     }

  176     //-----------------------------------------------------------------------------

  177     // 공백이나 널인지 확인

  178     // @return : boolean

  179     //-----------------------------------------------------------------------------

  180     String.prototype.isBlank = function() {

  181         var str = this.trim();

  182         for(var i = 0; i < str.length; i++) {

  183             if ((str.charAt(i) != "\t") && (str.charAt(i) != "\n") && (str.charAt(i)!="\r")) {

  184                 return false;

  185             }

  186         }

  187         return true;

  188     }

  189     //-----------------------------------------------------------------------------

  190     // 숫자로 구성되어 있는지 학인

  191     // arguments[0] : 허용할 문자셋

  192     // @return : boolean

  193     //-----------------------------------------------------------------------------

  194     String.prototype.isNum = function() {

  195         return (/^[0-9]+$/).test(this.remove(arguments[0])) ? true : false;

  196     }

  197     //-----------------------------------------------------------------------------

  198     // 영어만 허용 - arguments[0] : 추가 허용할 문자들

  199     // @return : boolean

  200     //-----------------------------------------------------------------------------

  201     String.prototype.isEng = function() {

  202         return (/^[a-zA-Z]+$/).test(this.remove(arguments[0])) ? true : false;

  203     }

  204     //-----------------------------------------------------------------------------

  205     // 숫자와 영어만 허용 - arguments[0] : 추가 허용할 문자들

  206     // @return : boolean

  207     //-----------------------------------------------------------------------------

  208     String.prototype.isEngNum = function() {

  209         return (/^[0-9a-zA-Z]+$/).test(this.remove(arguments[0])) ? true : false;

  210     }

  211     //-----------------------------------------------------------------------------

  212     // 숫자와 영어만 허용 - arguments[0] : 추가 허용할 문자들

  213     // @return : boolean

  214     //-----------------------------------------------------------------------------

  215     String.prototype.isNumEng = function() {

  216         return this.isEngNum(arguments[0]);

  217     }

  218     //-----------------------------------------------------------------------------

  219     // 아이디 체크 영어와 숫자만 체크 첫글자는 영어로 시작 - arguments[0] : 추가 허용할 문자들

  220     // @return : boolean

  221     //-----------------------------------------------------------------------------

  222     String.prototype.isUserid = function() {

  223         return (/^[a-zA-z]{1}[0-9a-zA-Z]+$/).test(this.remove(arguments[0])) ? true : false;

  224     }

  225     //-----------------------------------------------------------------------------

  226     // 한글 체크 - arguments[0] : 추가 허용할 문자들

  227     // @return : boolean

  228     //-----------------------------------------------------------------------------

  229     String.prototype.isKor = function() {

  230         return (/^[가-힣]+$/).test(this.remove(arguments[0])) ? true : false;

  231     }

  232     //-----------------------------------------------------------------------------

  233     // 주민번호 체크 - arguments[0] : 주민번호 구분자

  234     // XXXXXX-XXXXXXX

  235     // @return : boolean

  236     //-----------------------------------------------------------------------------

  237     String.prototype.isJumin = function() {

  238         var arg = arguments[0] ? arguments[0] : "";

  239         var jumin = eval("this.match(/[0-9]{2}[01]{1}[0-9]{1}[0123]{1}[0-9]{1}" + arg + "[1234]{1}[0-9]{6}$/)");

  240         if(jumin == null) {

  241             return false;

  242         }

  243         else {

  244             jumin = jumin.toString().num().toString();

  245         }

  246         // 생년월일 체크

  247         var birthYY = (parseInt(jumin.charAt(6)) == (1 ||2)) ? "19" : "20";

  248         birthYY += jumin.substr(0, 2);

  249         var birthMM = jumin.substr(2, 2) - 1;

  250         var birthDD = jumin.substr(4, 2);

  251         var birthDay = new Date(birthYY, birthMM, birthDD);

  252         if(birthDay.getYear() % 100 != jumin.substr(0,2) || birthDay.getMonth() != birthMM || birthDay.getDate() != birthDD) {

  253             return false;

  254         }       

  255         var sum = 0;

  256         var num = [2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5]

  257         var last = parseInt(jumin.charAt(12));

  258         for(var i = 0; i < 12; i++) {

  259             sum += parseInt(jumin.charAt(i)) * num[i];

  260         }

  261         return ((11 - sum % 11) % 10 == last) ? true : false;

  262     }

  263     //-----------------------------------------------------------------------------

  264     // 외국인 등록번호 체크 - arguments[0] : 등록번호 구분자

  265     // XXXXXX-XXXXXXX

  266     // @return : boolean

  267     //-----------------------------------------------------------------------------

  268     String.prototype.isForeign = function() {

  269         var arg = arguments[0] ? arguments[0] : "";

  270         var jumin = eval("this.match(/[0-9]{2}[01]{1}[0-9]{1}[0123]{1}[0-9]{1}" + arg + "[5678]{1}[0-9]{1}[02468]{1}[0-9]{2}[6789]{1}[0-9]{1}$/)");

  271         if(jumin == null) {

  272             return false;

  273         }

  274         else {

  275             jumin = jumin.toString().num().toString();

  276         }

  277         // 생년월일 체크

  278         var birthYY = (parseInt(jumin.charAt(6)) == (5 || 6)) ? "19" : "20";

  279         birthYY += jumin.substr(0, 2);

  280         var birthMM = jumin.substr(2, 2) - 1;

  281         var birthDD = jumin.substr(4, 2);

  282         var birthDay = new Date(birthYY, birthMM, birthDD);

  283         if(birthDay.getYear() % 100 != jumin.substr(0,2) || birthDay.getMonth() != birthMM || birthDay.getDate() != birthDD) {

  284             return false;

  285         }

  286         if((parseInt(jumin.charAt(7)) * 10 + parseInt(jumin.charAt(8))) % 2 != 0) {

  287             return false;

  288         }

  289         var sum = 0;

  290         var num = [2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5]

  291         var last = parseInt(jumin.charAt(12));

  292         for(var i = 0; i < 12; i++) {

  293             sum += parseInt(jumin.charAt(i)) * num[i];

  294         }

  295         return (((11 - sum % 11) % 10) + 2 == last) ? true : false;

  296     }   

  297     //-----------------------------------------------------------------------------

  298     // 사업자번호 체크 - arguments[0] : 등록번호 구분자

  299     // XX-XXX-XXXXX

  300     // @return : boolean

  301     //-----------------------------------------------------------------------------

  302     String.prototype.isBiznum = function() {

  303         var arg = arguments[0] ? arguments[0] : "";

  304         var biznum = eval("this.match(/[0-9]{3}" + arg + "[0-9]{2}" + arg + "[0-9]{5}$/)");

  305         if(biznum == null) {

  306             return false;

  307         }

  308         else {

  309             biznum = biznum.toString().num().toString();

  310         }

  311         var sum = parseInt(biznum.charAt(0));

  312         var num = [0, 3, 7, 1, 3, 7, 1, 3];

  313         for(var i = 1; i < 8; i++) sum += (parseInt(biznum.charAt(i)) * num[i]) % 10;

  314         sum += Math.floor(parseInt(parseInt(biznum.charAt(8))) * 5 / 10);

  315         sum += (parseInt(biznum.charAt(8)) * 5) % 10 + parseInt(biznum.charAt(9));

  316         return (sum % 10 == 0) ? true : false;

  317     }

  318     //-----------------------------------------------------------------------------

  319     // 법인 등록번호 체크 - arguments[0] : 등록번호 구분자

  320     // XXXXXX-XXXXXXX

  321     // @return : boolean

  322     //-----------------------------------------------------------------------------

  323     String.prototype.isCorpnum = function() {

  324         var arg = arguments[0] ? arguments[0] : "";

  325         var corpnum = eval("this.match(/[0-9]{6}" + arg + "[0-9]{7}$/)");

  326         if(corpnum == null) {

  327             return false;

  328         }

  329         else {

  330             corpnum = corpnum.toString().num().toString();

  331         }

  332         var sum = 0;

  333         var num = [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]

  334         var last = parseInt(corpnum.charAt(12));

  335         for(var i = 0; i < 12; i++) {

  336             sum += parseInt(corpnum.charAt(i)) * num[i];

  337         }

  338         return ((10 - sum % 10) % 10 == last) ? true : false;

  339     }

  340     //-----------------------------------------------------------------------------

  341     // 이메일의 유효성을 체크

  342     // @return : boolean

  343     //-----------------------------------------------------------------------------

  344     String.prototype.isEmail = function() {

  345         return (/\w+([-+.]\w+)*@\w+([-.]\w+)*\.[a-zA-Z]{2,4}$/).test(this.trim());

  346     }

  347     //-----------------------------------------------------------------------------

  348     // 전화번호 체크 - arguments[0] : 전화번호 구분자

  349     // @return : boolean

  350     //-----------------------------------------------------------------------------

  351     String.prototype.isPhone = function() {

  352         var arg = arguments[0] ? arguments[0] : "";

  353         return eval("(/(02|0[3-9]{1}[0-9]{1})" + arg + "[1-9]{1}[0-9]{2,3}" + arg + "[0-9]{4}$/).test(this)");

  354     }

  355     //-----------------------------------------------------------------------------

  356     // 핸드폰번호 체크 - arguments[0] : 핸드폰 구분자

  357     // @return : boolean

  358     //-----------------------------------------------------------------------------

  359     String.prototype.isMobile = function() {

  360         var arg = arguments[0] ? arguments[0] : "";

  361         return eval("(/01[016789]" + arg + "[1-9]{1}[0-9]{2,3}" + arg + "[0-9]{4}$/).test(this)");

  362     }

Trackback 0 Comment 0
2007/10/15 09:12

redhat 호환 rpms

http://dag.wieers.com/rpm/

http://rpm.pbone.net/

http://rpmfind.net/

Trackback 0 Comment 0
2007/10/15 08:45

여러라인 값 더하기

# cat a.log
1
2
3
4

# awk '{sum+=$1}END{print sum}'
 10

Trackback 0 Comment 0
2007/09/18 18:46

OpenSSH deny or restrict access to users and groups

http://www.cyberciti.biz/tips/openssh-deny-or-restrict-access-to-users-and-groups.html

OpenSSH has two directives for allowing and denying ssh user access.

DenyUsers user1 user2 user3

Use to block user login. You can use wild cards as well as user1@somedomain.com (user1 is not allowed to login from somedomain.com host) pattern.

DenyGroups group1 group2
A list of group names, if user is part of primary of supplementary group login access is denied. You can use wildcards.

Please note that you cannot use a numeric group or username ID. If these directives are not used, default is to allow everyone.

AllowUsers user1 user2
This directive is opposite of DenyUsers directive.

AllowGroups group1 group2
This directive is opposite of DenyGroups directive.

You should always block access to root user/group:
Open /etc/ssh/sshd_config file:

# vi /etc/ssh/sshd_config

Append following names (directives):

DenyUsers root finadmin
DenyGroups root finadmin

Make sure at least one user is allowed to use ’su -’ command.

Save the file and restart the sshd.

This is a secure setup and you are restricting the users allowed to access the system via SSH with four above directives.

Please note that if you want to deny or allow access to large number of users consider SSH PAM configuration (ideal for ISPs and Web hosting service providers). PAM allows you to store usernames using text files (you do not have to mess up with ssh configuration file).

Please subscribe to our free e-mail newsletter or full RSS feed to get all updates. Or just leave a reply/comment ( 12 ).

Trackback 0 Comment 0
2007/09/13 13:32

html auto refresh

<HTML>
<HEAD>
<TITLE>SEEBOX Network Monitoring System</TITLE>
<meta HTTP-EQUIV="REFRESH" CONTENT=50>
<meta HTTP-EQUIV="Expires" Content=0>
<meta HTTP-EQUIV="Pragma" CONTENT="no-cache">
</HEAD>
<FRAMESET cols="100%">
   <FRAME src="http://www.naver.com/">
</FRAMESET>
</HTML
Trackback 0 Comment 0
2007/09/13 13:29

Xwindows blank disable


/etc/X11/xorg.conf
-------------------------------------------------------------------
Section "ServerLayout"
    Identifier     "Default Layout"
    Screen      0  "Screen0" 0 0
    Screen      1  "Screen1" RightOf "Screen0"
    InputDevice    "Mouse0" "CorePointer"
    InputDevice    "Keyboard0" "CoreKeyboard"
    Option         "BlankTime"  "0"     # Blank the screen in 10 minutes (Fake)
    Option         "StandbyTime" "0"    # Turn off screen in 20 minutes (DPMS)
    Option         "SuspendTime" "0"    # Full hibernation in 30 minutes (DPMS)
    Option         "OffTime"    "0"     # Turn off DPMS monitor (DPMS)
EndSection
----------------------------------------------------------------------


* 위의 설정만으로 모니터꺼짐이 동작하지는 않을것이나 부가적으로 추가한다면
(1) gnome screen saver uninstall
# rpm -e gnome-screensaver

(2) xset command를  .xinitrc 에 추가함
      export DISPLAY=:0.0
      xset -display :0.0 -dpms
      xset -display :0.0 s off
      xset -display :0.0 s noblank
      xset -display :0.0 s noexpose
      export DISPLAY=:0.1
      xset -display :0.1 -dpms
      xset -display :0.1 s off
      xset -display :0.1 s noblank
      xset -display :0.1 s noexpose
모니터가 한개이면 -display는 없어도 될것임....
Trackback 0 Comment 0
2007/09/13 13:23

boot후 자동 로그인

1. root 자동 로그인
/etc/inittab
------------------------------------------------------------
# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty --autologin root tty1
2:2345:respawn:/sbin/mingetty --autologin root tty2
3:2345:respawn:/sbin/mingetty --autologin root tty3
4:2345:respawn:/sbin/mingetty --autologin root tty4
5:2345:respawn:/sbin/mingetty --autologin root tty5
6:2345:respawn:/sbin/mingetty --autologin root tty6
-------------------------------------------------------------

2. 특정 console에서만 어플리케이션 자동실행
/root/.bash_profile or /etc/profile
-------------------------------------------------------------
if `tty | grep tty1 >/dev/null` ; then
      startx &
      sleep 10
      export DISPLAY=:0.0
      thunderbird &
      export DISPLAY=:0.1
      firefox  file:///opt/monitoring/monitoring.html &
fi
--------------------------------------------------------------
Trackback 0 Comment 0
2007/09/09 15:56

SSH Tunneling with PuTTY

http://stania.pe.kr/wiki/Linux/PuttyTunneling

PuTTY 를 사용하여, 특정 사설 네트워크의 네트웍 자원에 쉽게 접근할 수 있는 방법을 소개한다. 전제조건으로, 당연히, 그 사설 네트워크 안의 리눅스 서버에 SSH 를 통해 접근할 수 있어야한다.

좀 더 실무적인 예를 들어보자.

S 대학 U 모 컴퓨터 관련 동아리에서는 U 모 서버가 동아리의 메인 리눅스 서버이자, 동아리 내 사설 네트웍의 방화벽/게이트웨이 역할을 한다. 나는 이 동아리의 일원으로서, U 모 서버의 ID 를 가지고 있다고 하자. U 모 동아리의 사설 네트워크 안의 V 모 서버에는 윈도우즈가 깔려 있으며, 이 컴퓨터를 터미널 서버로 (mstsc) 사용할 수 있도록 설정되어있다. U 모 서버에서, 포트 포워딩을 지원(?)하지 않는다고 가정하고, 집에서 V 모 서버로 mstsc 접속을 해보자.

아래의 설정은, 0.58 버전에서는 접속 후에도 언제든지 설정할 수 있지만, 0.56 에서는 초기 접속시에만 설정할 수 있었다.
  1. Connection - SSH - Tunnels 섹션의 Port Forwarding 에 적절한 값을 입력해야한다.
  2. Add new forwarded port: 부분을 잘 살펴본다. Source port 는 현재 내 시스템에 생길 입구 포트를 의미하며, Destination 이 앞서 지정한 포트로 접속했을 때의 출구를 의미한다. Source port 에 51234 정도를 입력해주고 (잘 안 쓰는 포트), Destination port 에 192.168.57.3:3389 를 입력해주자(여기서 사용된 IP 는 V 모 서버의 사설 네트워크용 아이피이다). 설정 후 Add 버튼을 눌러 리스트에 추가하는 걸 잊지 말자.
  3. 평소대로 U 모 서버에 접속, 로그인한다. PuTTY 는 계속 켜져있어야한다.
  4. mstsc 프로그램을 켜고 localhost:51234 포트로 접속한다. V 모 서버의 3389 포트로 접근한 것과 같은 효과가 난다.

이 방법의 장점은 다음과 같다.
  • 관리자 권한이 필요한 거창한 방화벽 설정 없이도 손쉽게 포트를 포워딩 할 수 있다.
  • 네트웍을 흐르는 정보가 SSH 위에서 돌아다니므로, 안전하게 데이터를 주고받을 수 있다.
단점도 있다.
  • SSH 암호화를 거치는 과정에서 속도가 약간 떨어질 수 있다.
  • 그래도 조금은 귀찮다.

때때로 매우 유용한 기능이라고 할 수 있다. 사용 방법이 무궁무진할 듯.

그 밖의 활용방법 #

방화벽 뚫기 삽질기 #

PuTTY 의 터널링중 Remote 기능을 사용해, 방화벽 안의 사용자가 돌리는 서버에, 다른 서버를 경유하여 접속할 수 있다.

요약 #

임의의 사용자는, 리눅스 서버인 서버 T를 통해, 실제로 윈도우 기반 웹서버 프로그램이 작동중인 컴퓨터 A 로 접속하게 된다. 컴퓨터 A 와 서버 T 사이엔 SSH 를 사용한 터널이 구축된다.

사전 요구사항 #

  • 서버 T 의 sshd 에서 GatewayPorts 설정이 yes 로 되어 있어야한다. (즉 서버 T 의 root 권한으로 sshd 의 설정을 바꿔줄 필요가 있다. 자세한 방법은 아래에서.)

터널링 설정 #

  • Source port : 서버 T 에서 연결을 받아들일(Listening) 포트를 설정한다. 여기서는 58080 으로 설정한다고 하자.
  • Destination port : Source Port 로 들어온 연결이 어느 쪽으로 흐를지 출구를 설정한다. SSH Client 가 동작하는 컴퓨터에서 접근 가능한 컴퓨터라면 어디든지 OK. 여기서는 컴퓨터 A 에서 웹서버가 돈다고 가정하고 있으므로, 127.0.0.1:80 이 되겠다.
  • Local/Remote/Dynamic 중 Remote 를 설정한다.

    위의 설정을 잘 끝낸 후 접속을 성공시키고 netstat 등을 실행시켜보면, 58080 포트(Source Port 에서 지정한 포트) 에서 연결을 받아들이고 있음을 확인할 수 있다. telnet 이나 웹브라우저(w3m, lynx)등을 사용하여 localhost:58080 으로 접속해보면 성공적으로 컴퓨터 A 의 웹서버에 접속할 수 있을 것이다.

    여기서 문제는, 대부분의 서버에서는 이 58080 포트를 통해 다른 컴퓨터들은 접속할 수 없다는 것이다. netstat -an 등을 수행해본 결과를 유심히 보면 알겠지만, listening 포트가 127.0.0.1:58080 등으로, localhost 에서만 접속할 수 있는 포트로 binding 되어있기 때문이다. 다른 컴퓨터들이 서버 T 의 58080 포트를 통해 컴퓨터 A 에 접근하기 위해선, 0.0.0.0:58080 에 bind 되어있어야한다. 이는 sshd 의 설정을 바꿔서 해결할 수 있다.

sshd 설정을 변경하여 다른 컴퓨터로부터의 접속 받아들이기 #

sshd 설정중 GatewayPorts 옵션은 기본값이 'no' 이다. 따라서 SSH 터널링을 사용해 만들어진 포트는, 기본적으로 다른 컴퓨터에서 접근할 수 없다. 하지만 저 옵션을 'yes' 로 만들어주면, SSH 터널링을 통해 만들어진 포트가 0.0.0.0:58080 에 bind 되면서 임의의 다른 호스트로부터의 접속을 받아들일 수 있게 된다. 이를 위해서는 sshd 의 설정을 변경해야 하므로, root 권한이 필요하다.
Trackback 0 Comment 0
2007/09/04 18:48

Linux Monitor Power Control

http://elibrary.fultus.com/technical/index.jsp?topic=/com.fultus.linux.howtos/howtos/Battery-Powered/powersav.html



2.4. XF86Config Tuning

There are essentially two different types of screen blanking that can be performed under X-Windows: BlankTime and DPMS. The first is simply a fake "blanking" effect that doesn't actually save any power. The others are specific only to DPMS-compliant monitors, and must be specifically enabled to take effect. They are located in your XF86Config file, which normally resides in /etc/X11/XF86Config.

DPMS (Display Power Management Signaling) is a standard to reduce power consumption in monitors [2]. Typically, both the monitor and the video card must support the DPMS standard in order to receive any benefit from it. DPMS specifies four modes of operation (in order of increasing power savings): "Normal", "Standby", "Suspend" and "Off". Two signal lines, "Horizontal Sync" and "Vertical Sync" provide a method for signaling these four different states to a DPMS monitor.

If you have a DPMS-compliant monitor, you might want to try enabling support for it under the Monitor section of your XF86Config file:

Section "Monitor"
	[... other values here ...]
	Option	"DPMS"
EndSection

To manipulate the DPMS functions, you can create/modify the following items in the ServerLayout section.

Section "ServerLayout"
	Option "BlankTime"	"10"	# Blank the screen in 10 minutes (Fake)
	Option "StandbyTime" 	"20"	# Turn off screen in 20 minutes (DPMS)
	Option "SuspendTime"	"30"	# Full hibernation in 30 minutes (DPMS)
	Option "OffTime"	"40"	# Turn off DPMS monitor (DPMS)
EndSection

BlankTime is not actually a power saving level at all. The screen is sent a "fake" blanking effect and defaults to activate after 10 minutes. Alternately, it can indicate the number of minutes until the screensaver should activate. It has nothing to do with DPMS.

StandbyTime is a very minor power saving level. This setting usually involves blanking the screen by turning off the electron (RGB) gun. However, the power supply is left on and the tube filaments energized. When you need to use the monitor again, the monitor will come back on very quickly. This option requires DPMS monitor/video-card support and defaults to 20 minutes under X-Windows. Also known as hsync suspend mode, since the horizontal sync signal is turned off to signal this power management state to a DPMS monitor.

SuspendTime is a very strong low power alternative. This setting usually involves the same power conservation as StandbyTime, however in addition the power supply is turned off. This option requires DPMS monitor/video-card support and defaults to 30 minutes under X-Windows. Also known as vsync suspend mode, since the vertical sync signal is turned off to signal this power management state to a DPMS monitor.

OffTime usually means just that. The computer monitor is turned off. A small auxiliary circuit stays on to monitor the signals from the computer to turn the monitor back on when data needs to be displayed to the screen. Obviously, this keeps power consumption to a bare minimum (zero). While the power saving is substantial, to reactivate the monitor may take up to 8-10 seconds. This option requires DPMS monitor/video-card support and defaults to 40 minutes under X-Windows. Both the horizontal and vertical sync signals are turned off to signal this power management state to a DPMS monitor.

After activating your changes and restarting X-Windows, you might want to examine your logfile to see if your video card has any problems with your changes:

$ egrep "^\(WW|EE\)" /var/log/XFree86.0.log

There may be additional options that you can enable for your specific video card/chip driver; see the XFree86 Documentation website for specifics.

Of course, all of this can also be activated "on-the-fly" by using xset(1). If you don't have access to your system's XF86Config file, a good place to put these commands would be in your ~/.Xsession or ~/.xinitrc file.

$ xset -dpms			# Disable DPMS
$ xset +dpms			# Enable DPMS
$ xset s off			# Disable screen blanking
$ xset s 150			# Blank the screen after 150 seconds
$ xset dpms 300 600 900		# Set standby, suspend, & off times (in seconds)
$ xset dpms force standby	# Immediately go into standby mode
$ xset dpms force suspend	# Immediately go into suspend mode
$ xset dpms force off		# Immediately turn off the monitor
$ xset -q			# Query current settings

If instead you're using the Linux console (not X-Windows), you'll want to use setterm(1):

$ setterm -blank 10		# Blank the screen in 10 minutes
$ setterm -powersave on		# Put the monitor into VESA power saving mode
$ setterm -powerdown 20		# Set the VESA powerdown to 20 minutes

2.5. Energy Star

Energy Star is a United States government-backed program to promote energy efficiency standards. Of interest:

  • An ENERGY STAR qualified computer, in sleep mode, uses 70% less electricity than computers without power management features.

  • An ENERGY STAR qualified monitor, in sleep mode, uses 90% less electricity than monitors without power management features.

Typically, Energy Star savings is accomplished by other power management settings and is not, in and of itself, a power management technique.

Trackback 0 Comment 0