linux find 샘플

Trend 2008. 2. 16. 00:55

real world FIND usage

sudo find / -type f -name *.jpg -exec cp {} . \; find . -type f -size +10000 -exec ls -al {} \; find . -atime +1 -type f -exec mv {} TMP \; # mv files older then 1 day to dir TMP find . -name "-F" -exec rm {} \; # a script error created a file called -F find . -exec grep -i "vds admin" {} \; find . \! -name "*.Z" -exec compress -f {} \; find . -type f \! -name "*.Z" \! -name ".comment" -print | tee -a /tmp/list find . -name *.ini find . -exec chmod 775 {} \; find . -user xuser1 -exec chown -R user2 {} \; find . -name ebtcom* find . -name mkbook find . -exec grep PW0 {} \; find . -exec grep -i "pw0" {} \; find . -atime +6 find . -atime +6 -exec ll | more find . -atime +6 -exec ll | more \; find . -atime +6 -exec ll \; find . -atime +6 -exec ls \; find . -atime +30 -exec ls \; find . -atime +30 -exec ls \; | wc -l find . -name auth* find . -exec grep -i plotme10 {}; find . -exec grep -i plotme10 {} \; find . -ls -exec grep 'PLOT_FORMAT 22' {} \; find . -print -exec grep 'PLOT_FORMAT 22' {} \; find . -print -exec grep 'PLOT_FORMAT' {} \; find . -print -exec grep 'PLOT_FORMAT' {} \; find ./machbook -exec chown 184 {} \; find . \! -name '*.Z' -exec compress {} \; find . \! -name "*.Z" -exec compress -f {} \; find /raid/03c/ecn -xdev -type f -print find /raid/03c/ecn -xdev -path -type f -print find / -name .ssh* -print | tee -a ssh-stuff find . -name "*font*" find . -name hpmcad* find . -name *fnt* find . -name hp_mcad* -print find . -grep Pld {} \; find . -exec grep Pld {} \; find . -exec grep Pld {} \; find . -exec grep PENWIDTH {} \; | more find . -name config.pro find . -name config.pro find /raid -type d ".local_sd_customize" -print find /raid -type d -name ".local_sd_customize" -print find /raid -type d -name ".local_sd_customize" -ok cp /raid/04d/MCAD-apps/I_Custom/SD_custom/site_sd_customize/user_filer_project_dirs {} \; find /raid -type d -name ".local_sd_customize" -exec cp /raid/04d/MCAD-apps/I_Custom/SD_custom/site_sd_customize/user_filer_project_dirs {} \; find . -name xeroxrelease find . -exec grep xeroxrelease {} \; find . -name xeroxrelease find . -name xeroxrelease* -print 2>/dev/null find . -name "*release*" 2>/dev/null find / -name "*xerox*" 2>/dev/null find . -exec grep -i xeroxrelease {} \; find . -print -exec grep -i xeroxrelease {} \; find . -print -exec grep -i xeroxrelease {} \; > xeroxrel.lis find . -exec grep -i xeroxrel {} \; find . -print -exec grep -i xeroxrel {} \; find . -print -exec grep -i xeroxrel {} \; | more find /raid/03c/inwork -xdev -type f -print >> /raid/04d/user_scripts/prt_list.tmp find . -exec grep '31.53' {} \; find . -ls -exec grep "31/.53" {} \; > this.lis find . -print -exec grep "31/.53" {} \; > this.lis find . -print -exec grep 31.53 {} \; > this.lis find . -exec grep -i pen {} /; find . -exec grep -i pen {} \; find . -print -exec grep -i pen {} \; | more find . -exec grep -i pen {} \; find . -atime +6 -exec ll | more \; find . -atime +6 -exec ll \; find . -atime +6 -exec ls \; find . -atime +30 -exec ls \; find . -atime +30 -exec ls \; | wc -l find . \! -name '*.Z' -exec compress -f {} \; find . -name 'cache*' -depth -exec rm {} \; find . -name 'cache*' -depth -print | tee -a /tmp/cachefiles find . -name 'cache[0-9][0-9]*' -depth -print | tee -a /tmp/cachefiles find . -name 'hp_catfile' 'hp_catlock' -depth -print | tee -a /tmp/hp.cats find . -name 'hp_catfile' -name 'hp_catlock' -depth -print | tee -a /tmp/hp.cats find . -name 'hp_cat*' -depth -print | tee -a /tmp/hp.cats find . -name 'hp_cat[fl]*' -depth -print | tee -a /tmp/hp.cats find /raid -name 'hp_cat[fl]*' -depth -print find . \! -name '*.Z' -exec compress -f {} \; find . -name '*' -exec compress -f {} \; find . -xdev -name "wshp1*" -print find . -xdev -name "wagoneer*" -print find . -name "xcmd" -depth -print find /usr/contrib/src -name "xcmd" -depth -print find /raid -type d -name ".local_sd_customize" -exec ls {} \; find /raid -type d -name ".local_sd_customize" \ -exec cp /raid/04d/MCAD-apps/I_Custom/SD_custom/site_sd_customize/user_filer_project_dirs {} \;

wagoneers.com




Select pages from WAGONEERS.COM:  <FORM name="SiteForm"><INPUT type="reset" value="원래대로"></FORM>


Buy this FSJ decal...   ...use PayPal to pay for it!






AMSOIL synthetic lubricants and filters
(please use customer #283461)



Shop AMAZON.com from wagoneers.com! 
<FORM action="http://www.amazon.com/exec/obidos/external-search" method="get">
Search:
Keywords: <INPUT size="10" name="keyword"> <INPUT type="hidden" value="wagoneerscom-20" name="tag"> <INPUT type="image" src="http://wagoneers.com/amazon/home-btn-120x90.gif" align=absMiddle value=Go border=0 name=Go>
</FORM>


these pages protected by US Copyright laws
John Meister copyright © 1995-2001 all rights reserved
contact john-at-wagoneers.com
"Join the fight against spam (UCE)! Eliminate spam!" Washington State has a $500 fine for "spam"
(unsolicited commercial email)!


      read the Bible

'Trend' 카테고리의 다른 글

구글 칼렌더 싱크  (0) 2008.03.18
버핏의 투자  (0) 2008.02.24
방화벽으로 웹 막기.  (0) 2008.02.12
Common Development and Distribution License (CDDL)  (0) 2008.01.21
리뷰 고고싱 게임?!!!  (0) 2008.01.21
Posted by '김용환'
,

How do I get awk to run shell scripts?

Use the system() function, e.g.:

cmd = "/bin/echo hello";
system(cmd);
close(cmd);

You can run anything you want with system(), not just shell scripts

 

 

 

출처 : http://hibernia.jakma.org/~paul/awk-faq.html#system

'c or linux' 카테고리의 다른 글

아파치의 rewriteRule 문제점  (0) 2008.02.28
gethostbyname, getaddrinfo 사용한 샘플 소스  (0) 2008.02.26
쉘 스크립트에서의 함수 파라미터  (0) 2007.09.11
ulimit  (0) 2007.09.10
crontab 에러  (0) 2007.09.08
Posted by '김용환'
,

방화벽으로 웹 막기.

Trend 2008. 2. 12. 11:22

[e6/home/www/script]# cat ./closeweb.pl
#!/usr/bin/perl

my $string=`ifconfig | grep 'inet addr' | awk '{print \$2}'`;
my @array = $string =~ /addr:(\d+.\d+.\d+.\d+)/g;
#print $_, "\n" foreach(@array); # ¹è¿­ Ãâ·Â

foreach $ip (@array) {
        chomp $ip;
        print "iptables -I INPUT -p tcp --dport 80 -d $ip -j DROP\n";
        my $result = `iptables -I INPUT -p tcp --dport 80 -d $ip -j DROP`;
}

'Trend' 카테고리의 다른 글

버핏의 투자  (0) 2008.02.24
linux find 샘플  (0) 2008.02.16
Common Development and Distribution License (CDDL)  (0) 2008.01.21
리뷰 고고싱 게임?!!!  (0) 2008.01.21
소켓에서 읽을 데이터가 없습니다 라고 에러가 날때  (0) 2008.01.14
Posted by '김용환'
,

quartz 를 이용하기

java UI 2008. 1. 22. 23:56

 <?xml version='1.0' encoding='MS949'?>
<!DOCTYPE quartz PUBLIC
  "-//Quartz Enterprise Job Scheduler//DTD Job Scheduling Data 1.5//EN"
  "http://www.quartzscheduler.org/dtd/job_scheduling_data_1_5.dtd">

<quartz>
  <job>

    <job-detail>
      <name>RankingCron</name>
      <group>RankingCrons</group>
      <job-class>com.google.beginning.bo.RankingCronBO</job-class>
      <volatility>false</volatility>
      <durability>false</durability>
      <recover>false</recover>
    </job-detail>

 

    <trigger>
 

      <cron>
        <name>60</name>
        <group>cacheTriggers</group>
        <job-name>RankingCron</job-name>
        <job-group>RankingCrons</job-group>
        <cron-expression>1 * * * * ?</cron-expression>
      </cron>

    </trigger>
  </job>

</quartz>

 

 

실제 자바 소스는 다음과 같다.

 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;


public class RankingCronBO  implements Job {
    private static Log log = LogFactory.getLog(RankingCronBO.class);

    public void execute(JobExecutionContext context)
            throws JobExecutionException {
        log.info("RankingCronBO");

    }
}

 

'java UI' 카테고리의 다른 글

WindowBuilder Pro  (0) 2011.09.01
jsp 2.0 사용시 예제  (0) 2009.01.01
File Connection Optiobal Package  (0) 2006.02.28
[펌] DataSource의 복제를 통한 다중 플레이어 생성방법  (0) 2005.12.02
jtable tutorial  (0) 2005.02.16
Posted by '김용환'
,
[Sun Solaris]
FAQ: Common Development and Distribution License (CDDL)
 

오픈솔라리스가 채택한 라이센스 CDDL 의 FAQ를 통해 그동안의 궁금증을 해결하시기 바랍니다.


  • CDDL 은 무엇이고 이것이 오픈솔라리스 프로그램을 위해 선택된 이유는 무엇입니까?
  • CDDL 은 OSI 에 의해 승인되었습니까?
  • 왜 또다른 오픈소스 라이센스를 만들었습니까?
  • 모든 솔라리스 운영체제가 CDDL 라이센스 하에 배포 될 예정입니까?
  • 왜 CDDL 은 MPL 을 기반으로 했습니까?
  • MPL 에 비해 어떠한 개선이 이루어 졌습니까?
  • copyleft 라이센스를 원했다면 왜 GPL 이나 LGPL 을 사용하지 않았습니까?
  • CDDL 에서 저작권은 어떻게 얘기하고 있습니까?
  • CDDL 하에 배포되는 코드가 다른 오픈 소스 라이센스하에 배포되는 소스와 결합될 수 있습니까?
  • 다중 라이센스는 어떻습니까? 제 코드를 CDDL 과 또 다른 라이센스 두개의 라이센스를 가지게 할 수 있습니까?
  • 저의 독점적인 제품에 CDDL 하에 배포되는 코드를 사용한다면 제 소스 코드를 반드시 공유해야 합니까?
  • 만약 오픈솔라리스 소스 베이스에 코드를 제공한다면 라이센스와 관련된 어떠한 일을 하도록 요구 받습니까?
  • M오픈 솔라리스 소스 코드의 일부를 취해서 다른 코드 베이스에서 사용해도 될까요?
  • 제가 수정한 오픈솔라리스 소스 코드를 재배포하거나 팔 수 있습니까?
  • 오픈솔라리스 소스 코드 혹은 바이너리를 상업적으로 사용할 수 있습니까?
  • 저의 프로젝트(오픈솔라리스 프로그램과 관계 없는)에 CDDL 을 사용할 수 있습니까?
  • 썬이 오픈솔라리스 소스 코드를 다시 회수할수도 있습니까?

CDDL 은 무엇이고 이것이 오픈솔라리스 프로그램을 위해 선택된 이유는 무엇입니까?

CDDL 은Common Development and Distribution License 의 약자입니다. 이 라이센스는 잘 알려진 Mozilla Public License(MPL) 를 채택하였고 어떠한 수정도 필요 없이 재사용이 가능하도록 만들었습니다. 우리는 오픈소스를 보호할 수 있는 copyleft 라이센스와 또한 상용의 목적을 위한 대규모의 개발 작업이 가능한 라이센스를 원했습니다.

CDDL 은 OSI 에 의해 승인되었습니까?

그렇습니다 CDDL 은 오픈 소스 정의 의 요구 조건을 만족시키고 있고 Open Source Initiative 에 의해 오픈소스 라이센스로 승인 받았습니다.

왜 또다른 오픈소스 라이센스를 만들었습니까?

현존 하는 다수의 오픈소스 라이센스를 검토 해 보았지만 오픈솔라리스 소스 코드에 적당한 것을 발견하지 못했습니다. 결국 필요에 가장 잘 맞는 라이센스(MPL) 을 수정해서 오픈소스 공헌자들의 권리를 좀 더 명확하게 명시하도록 하였습니다. CDDL 은 비슷한 목표를 가지고 있는 다른 오픈소스 프로젝트들에게 매력적이고 재사용이 가능하도록 디자인 되었습니다.

모든 솔라리스 운영체제가 CDDL 라이센스 하에 배포 될 예정입니까?

현재 가능한한 많은 양의 소스 코드를 CDDL 하에 공개하도록 계획하고 있습니다. 솔라리스 운영체제에서 사용되는 써드파티 오픈 소스들은 여전히 관련된 라이센스들 하에 사용이 가능할 것입니다. 예를 들어 오픈솔라리스 코드 베이스에 포함된 PerlPerl Artistic License 하에 배포 됩니다. 또한 오픈 소스로 공개하기가 불가능한 코드들은 바이너리 형태로 제공될 예정입니다. 로드맵 에서 특정 기술에 대한 공개 가능 여부를 살펴 보시기 바랍니다.

왜 CDDL 은 MPL 을 기반으로 했습니까?

MPL 은 잘 알려진 라이센스 이고 썬이 찾고 있던 몇가지 속성들을 가지고 있었습니다. 이러한 속성들은:

  • 소스 코드의 변경이 오픈소스 라이센스 하에서 공개가 가능하도록 하는 요구 조건;
  • 서로 다른 라이센스하에 있는 실행파일들의 배포 가능 여부;
  • "파일-기반" 의 수정사항 정의 및 이것에 의해 커버되는 소프트웨어;
  • 명시적인 저작권 라이센스.

MPL 에 비해 어떠한 개선이 이루어 졌습니까?

필요한 모든 MPL 의 장점들의 유지(위에서 언급했었던)하는 것과 더불어 CDDL 은 재사용 될 수 있도록 디자인 되었으며 좀 더 일반적으로 사용할 수 있도록 몇가지 개선점을 포함하고 있습니다:

  • 필수 공지 요건이 간소화됨;
  • 수정에 대한 정의가 명확해 짐으로써 사람들이 라이센스에 의해 커버가 되는 혹은 되지 않은 부분을 명확하게 이해할 수 있도록 도와 줌;
  • 법, 소송, 관할권 선택에 대한 우려사항들이 기술되었음;
  • 라이센스에 의해 커버되는 소프트웨어들이 특정 버전의 라이센스가 추가된데에 따른 선택을 가능하도록 함.

MPL 1.1 과 CDDL 의 차이점은 요약 설명 (PDF 파일) 을 참고 하시기 바랍니다.

copyleft 라이센스를 원했다면 왜 GPL 이나 LGPL 을 사용하지 않았습니까?

우리는 다른 라이센스 하에 배포되는 파일들과 같이 링크가 가능한 오픈소스 라이센스를 필요로 했었습니다. LGPL 같은 라이센스는 동적-링크 된 코드를 사용함으로써 이러한 방식을 허용하지만 우리는 다른 라이센스 하에 정적으로 링크된 소스를 이용해 링크한 소프트웨어를 배포할 수 있는 것도 필요로 했었습니다. 거기에 덧붙여서 다른 사람들이 오픈솔라리스에 다른 라이센스를 가지는 추가 기능을 더할 수 있도록 허용하기를 원했습니다. 이것은 오직 MPL 같은 라이센스 하에서만 가능한 일입니다; 그러나 우리는 MPL 을 사용할 수가 없었습니다. 다른 사용자들에게 재사용을 허락하는 "템플릿" 형태의 라이센스가 아니였기 때문입니다. 결과적으로 MPL을 수정하는 길을 택함으로써 다른 비슷한 상황의 사용자들이 라이센스를 재사용할 수 있는 템플릿 라이센스 같은 형태를 만들기로 결정했습니다.

CDDL 에서 저작권은 어떻게 얘기하고 있습니까?

CDDL 은 라이센스 하에 배포되는 코드들에 대한 명시적인 저작권을 제공합니다. 즉 이것은 CDDL 하에 배포되는 코드들의 사용, 수정 및 재배포가 코드의 배포자(썬을 포함한)에 대한 걱정이 필요 없이 자유롭다는 것을 의미 합니다.또한 어떠한 누구든 그들이 제공한 코드에 대한 저작권 침해 소송을 개발자에게 걸었을때 코드에 대한 권리를 회수함으로써 개발자들에게 저작권 소송을 거는 것을 단념시키는 조항이 있습니다..

CDDL 하에 배포되는 코드가 다른 오픈 소스 라이센스하에 배포되는 소스와 결합될 수 있습니까?

CDDL 은 파일 기반입니다. 즉 CDDL 하에 사용가능한 파일들은 그것이 오픈 소스든 혹은 독점적이든 다른 라이센스 하에 제공되는 파일들과 결합이 가능합니다. 그러나 다른 라이센스는 이러한 조합을 막는 또 다른 제약을 가지고 있을 수도 있습니다; 이러한 제약사항들을 읽고 인식하는 것은 전적으로 여러분의 책임입니다.

다중 라이센스는 어떻습니까? 제 코드를 CDDL 과 또 다른 라이센스 두개의 라이센스를 가지게 할 수 있습니까?

가능합니다. 여러분의 코드의 copyright 소유자가 여러분 자신이라면 CDDL 을 포함한 다중의 라이센스를 선택할 수 있습니다.

저의 독점적인 제품에 CDDL 하에 배포되는 코드를 사용한다면 제 소스 코드를 반드시 공유해야 합니까?

그렇습니다. CDDL 하에 라이센스된 어떠한 소스 파일들이나 이러한 파일들을 수정한 부분들을 전부 공유해야 합니다. 그러나 여러분의 독점적인 소스 파일들은 공유할 필요가 없습니다.

만약 오픈솔라리스 소스 베이스에 코드를 제공한다면 라이센스와 관련된 어떠한 일을 하도록 요구 받습니까?

오픈솔라리스 소스 베이스에 제겅된 코드들은 반드시 CDDL 하에서 사용이 가능해야 합니다. 그리고 본인이 사인한 Contributor Agreement 를 제출해야 합니다. 프로젝트마다 서로 다른 제출 절차가 있을 수 있습니다. 각 프로젝트 리더(프로젝트 페이지에 나와 있음) 와 상의하시기 바랍니다.

오픈 솔라리스 소스 코드의 일부를 취해서 다른 코드 베이스에서 사용해도 될까요?

예. 여러분이 CDDL 의 라이센스 규칙만 준수한다면 다른 프로젝트에서 오픈솔라리스 소스 코드를 사용할 수 있습니다.

제가 수정한 오픈솔라리스 소스 코드를 재배포하거나 팔 수 있습니까?

가능합니다. CDDL 하에서 코드를 수정하거나 재배포할 수 있고 원한다면 가격을 매길 수도 있습니다. 주의할 점은 CDDL 의 보호를 받는 코드를 이용해 빌드된 바이너리를 배포할때에는 CDDL 의 규칙을 만족시켜야 하고 해당 소스 코드를 CDDL 하에서 배포해야 합니다.

오픈솔라리스 소스 코드 혹은 바이너리를 상업적으로 사용할 수 있습니까?

오픈 솔라리스 소스 코드를 상업적인 제품에 사용했을때 가능합니다. 주의할 점은 CDDL 의 보호를 받는 코드를 이용해 빌드된 바이너리를 배포할때에는 CDDL 의 규칙을 만족시켜야 하고 해당 소스 코드를 CDDL 하에서 배포해야 합니다. 자세한 사항은 라이센스 를 참고하시기 바랍니다.

저의 프로젝트(오픈솔라리스 프로그램과 관계 없는)에 CDDL 을 사용할 수 있습니까?

사용 가능합니다. 라이센스는 어느 누구도 자유롭게 재사용할 수 있도록 만들어 졌습니다.

썬이 오픈솔라리스 소스 코드를 다시 회수할수도 있습니까?

그렇지 않습니다. 코드는 커뮤니티에 영원히 제공될 것입니다.

 

발췌

http://www.suntraining.co.kr/jsp/webzine/SolarisView.jsp?wz_code=831&category=1

Posted by '김용환'
,

리뷰 고고싱 게임?!!!

Trend 2008. 1. 21. 05:28

드디어 고고싱 게임이 프리 오픈 베타로 막을 열렸다.

 

http://gogo.hangame.com

 

게시판의 글을 살펴 보니, 게임 유저들은 예전 카트라이더의 아류가 될 것 인지, 카트라이더를 넘는 큰 대작이 될른지 의견이 분분하다.

 

자. 게임을 살펴 보자

 

 

게임 스타트를 해본다.

 

고고싱 게임을 로딩하면서 스크린샷을 보여준다.

 

만든 회사는 Gn 어디서 많이 봤는데..

 

 

맞다. 바로 써든 어택 개발사라는 것!!!

 

 

 

 

 

게임 로딩 샷이 사라지면, 다음과 같이 게임 서버 선택 메뉴가 나온다.

 

 

 

 

1번 게임 서버에 들어가본다.

 

 

 

나의 레벨이 나오고, 아이템 개인전, 아이템 단체전, 스피드 개인전, 스피드 단체전이 나온다.

 

 가운데는 게임 메뉴가 나오고

 

밑으로는 상점등과 같은 메뉴가 보이는데, 들어가보면, 튜닝도 할 수 있고, 자동차도 새로 살 수 있다.

 

 

 

 

직접 게임을 즐겨보자.

 

준비하기 버튼을 누르고 주인장이 게임하기 를 누르면 바로 게임은 시작된다.

 

레이싱 경기장 화면이 나오면서.... 게임은 시작된다.

 

 

 

 

 

게임을 시작하기 앞서 각각의 유저에서 로딩이 얼마나 되었는지 왼쪽 상단 화면에 나오고, 각 유저들이 100%가 되면 게임은 시작된다.

 

이 떄, 좌측키, 우측키, 상키, 하키를 더블 클릭할 때마다 재미있는 장면을 볼 수 있다.

 

 

 

 

 

자 게임을 시작해보자. 나 혼자 열심히 달리지만, 쉽지 않다.

 

아이템 전이라면 아이템을 먹으면 상단위에 아이템을 표시한다.

 

 

 

거의 카트라이더와 비슷하지만, 차이점이 많다.

 

 

내가 살펴본 카트라이더와 비교한 고고싱의 특징은 다음과 같다.

 

1. 3D 레이싱 게임이다.

2. 맵이 다양하다.

3. 뒤로 보고, 아이템 공격이 가능하다.

4. 단체전은 결승점을 통과한 유저들의 수에 비례하지, 1등에 따라 좌우되지 않는다. 그만큼 개인의 실력이 단체전에서 중요하다.

5. 드리프트가 훨씬 재미있다.

6. 속도감이 많이 난다.다이나믹하다.

7. 스키드 러쉬와 같은 자동차 튜닝 요소가 있다.

8. 다양한 아이템이 많다. 즉 자동차에 독특한 아이템을 설정가능하다.

 

이렇게 다양한 특징이 있기 때문에 카트라이더를 넘어설 수 있는 부분이 많다고 생각된다

 

 

자... 그러면 함 고고싱을 하고 싶지 않은가??

 

 

말이 필요없다.  자 가자 고고싱!!

 

http://gogo.hangame.com

 

 

 

 

 

Posted by '김용환'
,

 

출처 :

http://j2k.naver.com/j2k_frame.php/korean/www.nurs.or.jp/~sug/soft/log4j/log4php2.htm

 

 

Log4J철저 해설

Log4php 의 Appender 들

목차


LoggerAppenderConsole

표준 출력 or 표준 에러 출력에 로그를 낸다.이것은 LoggerAppenderEcho (와)과는 달라, 성실하게 php://stdout 등을 열어 낸다.ConsoleAppender(을)를 참조.

옵션은 다음과 같이.

Target
STDOUT 인가 STDERR (을)를 취한다.각각 표준 출력이나 표준 에러 출력이다.디폴트 STDOUT.
layout
필수
Threshold
레벨을 지정해, 그 레벨 이하라고 출력하지 않게 하는 반응을 일으키는 최소의 물리량.모든 Appender 의 공통 옵션.

그리고,PHP 의 경우는 까다로운 것에, 별계통의 출력으로서 echo 하지만 있다.버퍼링이 별계통이 되므로, 같은 표준 출력에 낸다고 해도, 차례가 전후 하는 일이 있다.조금 실험해 보자.코드는 이런 곳.

이용 코드
<?php
require_once( '/usr/local/share/log4php/LoggerManager.php' );
$logger =& LoggerManager::getLogger('Sug.Test');

echo "echo 1\n";
print "print 2\n";
$fp = @fopen( 'php://stdout', 'w');
@fwrite($fp, "php://stdout 3\n" );
$logger->info( "logger.info 4" );
@fwrite($fp, "php://stdout 5\n" );
print "print 6\n";
echo "echo 7\n";
?>

log4php.properties
log4php.appender.echo=LoggerAppenderEcho
log4php.appender.echo.layout=LoggerPatternLayout
log4php.appender.echo.layout.ConversionPattern=echo %d %5p %c{1} - %m%n

log4php.appender.console=LoggerAppenderConsole
log4php.appender.console.Target=STDOUT
log4php.appender.console.layout=LoggerPatternLayout
log4php.appender.console.layout.ConversionPattern=console %d %5p %c{1} - %m%n

log4php.logger.Sug.Test=debug, console, echo
log4php.rootLogger=debug

이 출력은, 필자의 실험에서는,

$ php test.php
php://stdout 3
console 2006-04-08 12:10:26,095  INFO Test - logger.info 4
php://stdout 5
echo 1
print 2
echo 2006-04-08 12:10:26,095  INFO Test - logger.info 4
print 6
echo 7

그렇다고 하는 너무 재미있는 결과가 되었다....요컨데,

  1. 소스의 print, echo, log4php 의 LoggerAppenderEcho
  2. 「php://stdout」에의 fwrite (와)과 log4php 의 LoggerAppenderConsole

의 2 그룹에서 2개의 버퍼링이 있는 것 같다.그 말은,

출력의 차례를 신경쓴다면,LoggerApenderConsole (은)는 사용해서는 안된다.LoggerAppenderEcho (을)를 사용하세요.

LoggerAppenderEcho

이것은 표준 출력에 로그가 나오지만,PHP 의 echo (을)를 사용해 낸다.로그가 나오는 상태가 조금 다른 것으로,LoggerAppenderConsole 보다 여기를 좋아하는 사람이 많을 것이다.

옵션은 다음과 같이.고유 옵션은 없다.

layout
필수
Threshold
레벨을 지정해, 그 레벨 이하라고 출력하지 않게 하는 반응을 일으키는 최소의 물리량.모든 Appender 의 공통 옵션.

문제에 대해서는 LoggerAppenderConsole (을)를 참조.

LoggerAppenderFile

파일에 출력한다.FileAppender(을)를 참조.

PHP 어째서 , 실제의 출력은 「@fwrite()」(으)로 내고 있다.요컨데 어떤 에러가 발생해도 「무시!」이므로, 로그로테이트에는 이 Appender (은)는 전혀 사용할 수 없다.

옵션은 다음과 같이.

Append
true or false.추가 모드인가 아닌가.디폴트 true 그리고 추가 모드.
FileName
File
왜 2나 있을까...수수께끼이지만,FileName (분)편이 정규와 같이 생각한다.출력해야 할 파일명을 세트 한다.덧붙여 파일 출력계 Appender 그럼 이 2개의 옵션의 역할이 비묘 다른 케이스가 있으므로, 조심해.
layout
필수
Threshold
레벨을 지정해, 그 레벨 이하라고 출력하지 않게 하는 반응을 일으키는 최소의 물리량.모든 Appender 의 공통 옵션.

LoggerAppenderRollingFile

파일에 출력해, 사이즈 베이스의 로테이션을 한다.RollingAppender(을)를 참조.

동작은,FileName 옵션으로 지정된 파일에 로그를 출력해, 만약, 그 사이즈가 MaxFileSize (을)를 넘으면, 출력 파일을 닫고, 이름을 FileName.1 (으)로 변경한다.그리고, 신규의 출력 파일로서 FileName (을)를 작성한다.백업파일명은 단지 확장자(extension)만으로 구별해, 새로운 것으로부터 순서에 1, 2, 3... (와)과 차여서 가MaxBackupIndex (을)를 넘는 백업파일은 로테이션의 결과로서 소멸한다.

옵션은 다음과 같이.

MaxBackupIndex
최대 유지하는 백업파일의 수.== 3 (이)라면,FileName.3 까지 존재할 수 있다.디폴트 1 그리고 FileName.1 만 백업파일이 된다.
MaxFileSize
MaximumFileSize
1개의 파일의 최대 사이즈.요컨데 로그 출력의 결과 이 사이즈를 넘으면, 더이상 이 파일에는 추가하지 않고 로테이션 한다.디폴트는 10485760 byte(10Mbyte).동작은 2개 모두 같다.KB, MB, GB (와)과 숫자의 뒤에 단위를 붙일 수 있다.
FileName
이것은 덧쓰기되고 있다.File 옵션은 이 Appender 그럼 사용하지 않는다.파일의 베이스명(및 신규 로그의 출력 파일명)을 여기서 지정한다.
Append
true or false.추가 모드인가 아닌가.디폴트 true 그리고 추가 모드.
layout
필수
Threshold
레벨을 지정해, 그 레벨 이하라고 출력하지 않게 하는 반응을 일으키는 최소의 물리량.모든 Appender 의 공통 옵션.

LoggerAppenderDailyFile

파일 출력의 Appender.이것은DailyRollingAppender(와)과는 비슷하면서도 다른 것이다.기동시의 시간부터 파일명을 만들어낼 만한 것으로, 로테이션은 전혀 하지 않는다.서버 로그를 기록하는 경우에는, 최초로 기동한 시간의 파일명으로 연연 로그가 놓쳐 일절의 로테이션이 없기 때문에, 여기를 사용해서는 안된데.

옵션은 다음과 같이.

DatePattern
파일명의 패턴을 지정한다.디폴트는 「Ymd」.이 디폴트로부터 알도록(듯이), 요컨데 date() 하지만 접수서식 지정이라면 뭐든지OK.
File
출력 파일명이지만, 요주의.여기서의 지정에서는 「mylog%s.log」라고 하도록(듯이), 반드시 「%s」(을)를 포함하지 않으면 안 된다.요컨데,
    function setFile()
    {
        $numargs = func_num_args();
        $args    = func_get_args();
        
        if ($numargs == 1 and is_string($args[0])) {
            parent::setFile( sprintf((string)$args[0], date($this->getDatePattern())) );
        } elseif ($numargs == 2 and is_string($args[0]) and is_bool($args[1])) {
            parent::setFile( sprintf((string)$args[0], date($this->getDatePattern())), $args[1] );
        }
    } 

(와)과 하고 있어DatePattern 그리고 지정했다 date() 의 서식에 응한 지금의 일시 표현을,File 옵션의 「%s」의 위치에 삽입하게 된다.그리고,FileName 옵션은 이 Appender 그럼 사용하지 않는다(세트 가능하지만, 무시된다).
Append
true or false.추가 모드인가 아닌가.디폴트 true 그리고 추가 모드.
layout
필수
Threshold
레벨을 지정해, 그 레벨 이하라고 출력하지 않게 하는 반응을 일으키는 최소의 물리량.모든 Appender 의 공통 옵션.

LoggerAppenderDb

JDBCAppender(을)를 참조.JDBCAppender 에 가까운,SQL (을)를 스스로 구축해DB에 출력하는 것이다.하지만, 왠지 추천 테이블이 있기도 하는 근처 어중간하다.

그리고, 이것은 PEAR 의 DB 모듈을 이용해 만들어져 있다.그렇다면 뭐,PHP 의 DB 서포트는 각DB마다 고유한 함수를 호출해 주는 것이니까, 조금 추상 레이어를 갖고 싶은 것이다.(이)라고 해도 그 추상 레이어는 PHP 의 코어로 실장되고 있는 것이 아니라,PEAR(Perl 의 CPAN 같은 것이다)로 서포트되고 있다.

PEAR (은)는 대메이저인 프로젝트이므로,PHP 코어의 분이라도, 최근에는 PEAR 그리고 개발된 패키지를 함께 해 디스트리뷰션으로 하고 있는 것이 많다.그래서, 사용하기 전에 당신의 환경이 PEAR 의 DB 패키지를 서포트하고 있을지, 확인해 보자.

# pear info DB
About DB-1.6.2
==============
Provides        Classes:
Package         DB
Summary         Database Abstraction Layer
Description     DB is a database abstraction layer providing:
                
Maintainers     Stig S?her Bakken  (developer)
                
Version         1.6.2
Release Date    2004-04-07
Release License PHP License
Release State   stable
Release Notes   =============
                BUGS FIXED:
                
Release Deps    PHP >= 4.2.0
                Package PEAR >= 1.0b1
Last Modified   2004-10-15

같이 pear 커멘드가 있고, 한편 이와 같이 DB 패키지의 정보를 줍기 시작할 수 있으면OK(이)다.만약, 없으면,

# pear install DB

그리고, 넷에 연결되고 있는 환경이라면 인스톨 할 수 있다.

그리고,LoggerAppenderDB (은)는 이 DB 패키지를 이용하고 있어, 대개의DB(을)를 이용할 수 있을 것이다.

옵션은 다음과 같이.

Dsn
이것은DB(을)를 지정한다URL의,DB판의 것이다.일반 형식은,
phptype://username:password@protocol+hostspec:port//database?옵션

같은 모습이 된다.뭐, 보통은,
DB명 어카운트 패스워드 호스트 Database명
Mysql sug (none) localhost logs

정도로 사용하는 것이 많을테니, 이 옵션은
mysql://sug@localhost/logs

(이)가 되는 것이다.
Table
그DB중(안)에서 대상으로 하는 테이블명.
Sql
INSERT 해야 할SQL커멘드.그리고, 이것은 이 옵션으로 지정된 값을,LoggerPatternLayout 그리고 정형하고, 실제의SQL커멘드로 한다.
CreateTable
그리고, 이것이 문제의 옵션.true or false 그리고 디폴트 true 이다.이름대로, 마음대로 테이블을 만들어 준다.하지만, 만들어 주는 테이블의 schema는, 현상이라고 소스를 보지 않으면 원으로부터....그래서, 작성SQL(을)를 여기에 나타낸다.
CREATE TABLE Table옵션치 (
   timestamp varchar(32),
   logger varchar(32),
   level varchar(32),
   message varchar(64),
   thread varchar(32),
   file varchar(64),
   line varchar(4)
};

뭐, 이것을 보고 불만의 방향이 상당히 있을 것이다....message 하지만 너무 작지 말아라.마음에 들지 않으면, 스스로 마음대로 테이블을 만들어 줘.그리고 후, 이 옵션을 true (으)로 해 둔 채로도 전혀 문제는 일어나지 않지만, 당연한 일이면서 「테이블이 있을지?」(은)는, 로가-의 기동시에 하나 하나DB까지 체크하러 간다.이것을 속이 메스껍다고 생각한다면, 테이블을 만든 다음은, 이 옵션을 false (으)로 해 두자.물론, 여기서 지정한 유저 어카운트로, 테이블 작성을 할 수 있는 것이 전제인 것은 물론이다.그렇지 않으면,GRANT 라든가 적당하게 끝내고 나서 해 주어.
레이아웃
불요
Threshold
레벨을 지정해, 그 레벨 이하라고 출력하지 않게 하는 반응을 일으키는 최소의 물리량.모든 Appender 의 공통 옵션.

그래서,CreateTable 옵션으로 테이블을 만든 표준적인 케이스를 상정했다 Sql 옵션은, 다음과 같은 것이 된다.

                           타임 스탬프 레벨  스렛드   발생행
                               ↓         ↓        ↓        ↓
INSERT INTO 테이블명 VALUES('%d','%c','%p','%m','%t','%F','%L' )
                                    ↑        ↑        ↑
                                 카테고리 메세지 파일명  

만약, 필드 사이즈까지 지정해 둔다면 조심이 좋다( 「-」=왼쪽 채워 「min.max」).

INSERT INTO 테이블명 VALUES('%-.32d','%-.32c','%-.32p','%-.64m','%-.32t','%-.64F','%-.4L' )

그렇다고는 해도,MySQL 그리고 한 한계, 초과 자수는 특히 필드 사이즈를 지정하지 않아도 마음대로 끊어지는 것 같다.만약을 위해 설정예를 나타낸다.특히 Sql 옵션은, 이스케이프 관련으로 걸리는지, 「"~"」(으)로 쿠트 해 두지 않으면 에러가 되는 것 같다.

log4php.appender.db=LoggerAppenderDb
log4php.appender.db.Table="log4php"
log4php.appender.db.CreateTable=true
log4php.appender.db.Dsn="mysql://root@localhost/log4j"
log4php.appender.db.Sql="INSERT INTO log4php VALUES('%-.32d','%-.32c','%-.32p','%-.64m','%-.32t','%-.64F','%-.4L' )"

LoggerAppenderMail

SMTPAppender(을)를 참조.왠지 메일 송신Appender 하지만 2나 있지만, 여기는 로가-가 끝날 때까지 로그를 메일 본문에 모아 두고, 로가-가 종료(shutdown) 하면, 단번에 메일을 보낸다...(이)라는 것이다.그러니까, 로가-가 불렸을 때에는, 메일을 보내거나는 하지 않는다.Log4J 의 SMTPAppender 에서 만난 것 같은 순환 버퍼같은 멋부린 것은 없는 것이다.

옵션은 다음과 같이.

From
송신원을 지정한다.
To
송신지를 지정한다.
Subject
송신 타이틀을 지정한다.
layout
필수
Threshold
레벨을 지정해, 그 레벨 이하라고 출력하지 않게 하는 반응을 일으키는 최소의 물리량.모든 Appender 의 공통 옵션.

이것으로 보내진 메일은 다음과 같이 된다.

Return-Path: 
X-Original-To: sug@localhost.kobe-du.ac.jp
Delivered-To: sug@localhost.kobe-du.ac.jp
Received: by bizet.kobe-du.ac.jp (Postfix, from userid 1000)
        id 8ED106FD28; Sat,  8 Apr 2006 16:03:51 +0900 (JST)
To: sug@localhost.kobe-du.ac.jp
Subject: test mail from php
From: root@localhost.kobe-du.ac.jp
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit
Message-Id: <20060408070351.8ED106FD28@bizet.kobe-du.ac.jp>
Date: Sat,  8 Apr 2006 16:03:51 +0900 (JST)
Status: R

2006-04-08 16:03:51,296  INFO Test - test start
2006-04-08 16:03:51,300  WARN Test - Warning Message
2006-04-08 16:03:51,302 ERROR Test - ERROR MESSAGE
2006-04-08 16:03:51,305 FATAL Test - FATAL MESSAGE
2006-04-08 16:03:51,308 DEBUG Test - only debug
2006-04-08 16:03:51,310  INFO Test - test end

그리고, 지금부터 문제다.이 Appender (은)는 「로가-가 종료되면 메일을 보낸다」동작을 한다.그 말은 「로가-가 종료된다」라고는 무슨 일인가?그렇다고 하는 문제가 생겨 버린다.단지 스크립트가 종료한 것 만으로는, 「로가-가 종료되었다」되어 주지 않는 것이다.

즉, 이것은 명시적으로 「로가-의 종료」를 호출하지 않으면 움직이지 않는다.구체적으로는,

<?php
require_once( '../log4php-0.9/src/log4php/LoggerManager.php' );
$logger =& LoggerManager::getLogger('Sug.Test');

$logger->info( 'test start' );
$logger->warn( 'Warning Message' );
$logger->error( 'ERROR MESSAGE' );
$logger->fatal( 'FATAL MESSAGE' );
echo "test body\n";
$logger->debug( 'only debug' );
$logger->info( 'test end' );

# 명시적인 로가-의 종료
$logger->shutdown();
?>

하지만 필요한 것으로 있다.Logger 의 shutdown() (은)는 그 Logger 에 묶을 수 있었다 Appender 의 shutdown() 에 파급해,LoggerAppenderMail 의 close() (을)를 호출하고, 메일이 보내진다, 라고 하는 치수다.다른 Appender 의 경우는 단순한 클로우즈 처리 정도밖에 하고 있지 않지만,LoggerAppenderMail 그럼 최대중요인 기능이 close() 에 실장되어 버리고 있다.조심하지 않지 않으면.

그리고, 나머지 하나 더 중대한 포인트가 있다.그것은 「외국인이 개발한 것이므로,mail() 그리고 메일을 보내 버린다」라고 하는 것이다.이것을 핵 해 mb_send_mail() 그리고 옮겨놓는지,php.ini 그렇지만 만지고,mbstring.func_overload=1 (으)로 할까 하지 않으면 일본어 메일은 보낼 수 없다.

LoggerAppenderMailEvent

여기는 로그 이벤트가 발생하면 메일을 그때마다 보낸다.debug 레벨로 보내거나 하면 메체 번거롭다고 생각한다....하지만 그런데도,LoggerAppenderMail 밖에 없으면, 유저의 불만이 폭발하지 않을까?

옵션은 다음과 같이.아무래도 이 Appender 하 LoggerAppenderMail 의 다시 만들어 냄새나고, 2개만 옵션이 증가하고 있다.

From
송신원을 지정한다.
To
송신지를 지정한다.
Subject
송신 타이틀을 지정한다.
SmtpHost
메일 송신을 받아들인다 SMTP 서버가 서있는 호스트를 지정한다.
Port
메일 송신을 받아들인다 SMTP 서버가 리슨 하고 있는 호스트를 지정한다.디폴트는 당연 25.
layout
필수
Threshold
레벨을 지정해, 그 레벨 이하라고 출력하지 않게 하는 반응을 일으키는 최소의 물리량.모든 Appender 의 공통 옵션.

그리고, 증가했다 SmtpHost (와)과 Port 의 옵션은 옵셔널인 물건이므로, 지정하지 않아도 대개의 경우OK일 것이다.요컨데,PHP 의 코어인 프롭퍼티로서SMTP, smtp_port 하지만 있어, 디폴트가 localhost (와)과 25 (이)가 되어 있다.요컨데 mail() (은)는 이것을 사용해 메일 송신의 접속처를 특정하고 있는 것이다.그리고, 이 Appender 의 SmtpHost 옵션은, 시스템의 SMTP 프롭퍼티를 일시적으로 고쳐 쓰는 것이다....현실적으로 생각하고, 이것을 지정하지 않으면 안 되는 장면은 상상하기 어렵다.프록시가 사이에는님은 있는 케이스라면, 그렇다면 php.ini (을)를 고쳐 쓰겠지.용도는 거의 없다고 생각한다.

불평 늘어지는 것은 그만두고, 설정예다.Threshold 옵션은 이런 때에야말로 활용하자.

log4php.appender.mail=LoggerAppenderMailEvent
log4php.appender.mail.From="root@localhost"
log4php.appender.mail.To="sug@localhost"
log4php.appender.mail.layout=LoggerPatternLayout
log4php.appender.mail.layout.ConversionPattern="%d %5p %c{1} - %m%n"
log4php.appender.mail.Subject="test mail from php"
log4php.appender.mail.Threshold=WARN

LoggerAppenderSocket

SocketAppender(을)를 참조.소켓으로 송신한다.log4J 의 SocketAppender (은)는,Java 의 시리아라이제이션을 사용해 LoggingEvent (을)를 송신했지만, 이 LoggerAppenderSocket 에도 비슷한 사양이 있다.

옵션은 다음과 같이.

RemoteHost
Hostname
양쪽 모두 송신해야 할 서버의 호스트명을 지정한다.Hostname (분)편은 Deprecated 그래서,RemoteHost 만을 사용해야 한다.
Port
송신해야 할 서버가 리슨 하고 있는 포토 번호.디폴트는 4446.
Timeout
서버가 연결되지 않을 때에, 단념하기 위한 타임 아웃 시간.단위는 초.디폴트는 30(초).
LocationInfo
log4php 그럼, 로그의 발생행·파일명·발생 함수명을 줍기 시작하는데, 일부러 스택 트레이스를 보고 데이터를 구축하지 않으면 안 된다.그러니까, 「로그 이벤트를 보낸다」때에 이것을 구축해 보낼지가 옵션이다.디폴트는 false (이어)여, 구축하지 않고 보내지 않는다....하지만, 버그가 있다.true (으)로 하면,
Fatal error: Call to undefined function:  getlocationinfo() in /home/sug/.../lo
  g4php/appenders/LoggerAppenderSocket.php on line 270

(와)과 에러 해 준다.마음대로 해 줘.
UseXml
log4php 그럼, 로그 이벤트를 보낼 때에 2방법의 보내는 방법이 생긴다.하나는 PHP 의 오브젝트·시리아라이제이션을 사용해 보내는 방식이며, 하나 더는 XML 그리고 보내는 방식이다.이 어느 쪽인지를 이 옵션으로 지정한다.디폴트는 false (이어)여, 오브젝트·시리아라이제이션으로 보낸다.
Log4jNamespace
UseXml 옵션이 true(XML그리고 보낸다) 케이스로, 로그 이벤트는 LoggerXmlLayout 그리고 정형되어 보내지지만, 그 때에 사용하는 이름 공간을 Log4j 의 것으로 하는지,Log4php 의 것으로 하는지를 선택한다.디폴트는 false 이다.
layout
불요
Threshold
레벨을 지정해, 그 레벨 이하라고 출력하지 않게 하는 반응을 일으키는 최소의 물리량.모든 Appender 의 공통 옵션.

뭐이것은 실험이다.이런 설정 파일로 좋을 것이다.

log4php.appender.socket=LoggerAppenderSocket
log4php.appender.socket.Remotehost="localhost"
log4php.appender.socket.Port=4329
log4php.appender.socket.UseXml=false
# log4php.appender.socket.Log4jNamespace=true

그리고, 적당한 서버 프로그램으로 4329차례를 감시 하게 한다.거기에 테스트 프로그램으로부터 LoggerAppenderSocket (을)를 사용해 보내면, 이렇게 된다.

# java temp.MyServer
read from /127.0.0.1: O:18:"loggerloggingevent":10:{s:4:"fqcn";s:14:"LoggerCat
egory";s:12:"categoryName";s:8:"Sug.Test";s:5:"level";O:11:"loggerlevel":3:{s:
5:"level";i:50000;s:8:"levelStr";s:5:"FATAL";s:16:"syslogEquivalent";i:0;}s:3:
"ndc";N;s:17:"ndcLookupRequired";b:1;s:7:"message";s:13:"FATAL MESSAGE";s:15:"
renderedMessage";N;s:10:"threadName";N;s:9:"timestamp";N;s:12:"locationInfo";N
;}
Disconnected: /127.0.0.1

뭐, 이런 시리아라이제이션 사양을 PHP (은)는 가지고 있는 것이다.만약, 서버를 PHP 그리고 쓰고,seriarize() ⇔ unserialize() 그리고 바탕으로 되돌리면, 오브젝트를 재생할 수 있게 되는 것이다.다음은,

log4php.appender.socket.UseXml=true

(으)로서 하고,XML그리고 이벤트를 보낸 결과이다.

read from /127.0.0.1: <log4j:event logger="Sug.Test" level="FATAL"
 thread="1167" timestamp="1144483927497">
read from /127.0.0.1: <log4j:message><![CDATA[FATAL MESSAGE]]></log4j:message>
read from /127.0.0.1: <log4j:locationInfo class="main" file=
"/home/sug/public_html/soft/log4j/php/mytest.php" line="10" method="main" />
read from /127.0.0.1: </log4j:event>

어머나... LocationInfo 하 false 일텐데,LocationInfo (을)를 보내 버리고 있다...명백하게 버그야.한층 더 여기서 신경이 쓰이는 것은 Log4jNamespace = 미정도리 == false 일텐데, 이 XML 의 이름 공간이 「log4j:」일이다.예를 들어와 같이 LoggerXmlLayout 그리고,

log4php.appender.echo=LoggerAppenderEcho
log4php.appender.echo.layout=LoggerXmlLayout
log4php.appender.echo.layout.Log4jNamespace=false

(와)과 하고 주면, 올바르고 「log4php:」의 이름 공간을 사용해 준다.

<log4php:event logger="Sug.Test" level="FATAL" thread="1188" timestamp="1144484562539">
<log4php:message><![CDATA[FATAL MESSAGE]]></log4php:message>
<log4php:locationInfo class="main" 
file="/home/sug/public_html/soft/log4j/php/mytest.php" line="10" method="main" />
</log4php:event>

버그같지만 우선 「log4j:」의 이름 공간이 Chainsaw 등의 호환성은 좋기 때문에, 영향은 적은가.무엇인가 버그가 많다...

LoggerAppenderPhp

이것은 log4php 독자적인 사양.요컨데 PHP 하지만 가지고 있는 에러 처리의 기구를 사용하고 로그를 한다.trigger_error() (을)를 부르는 것이다.

옵션은 다음과 같이.특히 아무것도 필요 없다.

layout
불요
Threshold
레벨을 지정해, 그 레벨 이하라고 출력하지 않게 하는 반응을 일으키는 최소의 물리량.모든 Appender 의 공통 옵션.

그리고,log4php 의 로그 레벨과PHP 의 에러 레벨과의 대응 관계는 이러하다.

log4php PHP
DEBUG E_USER_NOTICE
INFO E_USER_NOTICE
WARN E_USER_WARNING
ERROR E_USER_ERROR
FATAL E_USER_ERROR

그리고, 실제 이 에러를 발생 시켜 보자.표시는 LoggerAppenderEcho (와)과 겹치게 하기로 한다.

echo 2006-04-08 17:45:36,543  INFO Test - test start

Notice: Sat Apr  8 17:45:36 2006,543 [1260] INFO Sug.Test - test start
 in /usr/local/share/log4php/appenders/LoggerAppenderPhp.php on line 80
echo 2006-04-08 17:45:36,545  WARN Test - Warning Message

Warning: Sat Apr  8 17:45:36 2006,545 [1260] WARN Sug.Test - Warning Message
 in /usr/local/share/log4php/appenders/LoggerAppenderPhp.php on line 78
echo 2006-04-08 17:45:36,547 ERROR Test - ERROR MESSAGE

Fatal error: Sat Apr  8 17:45:36 2006,547 [1260] ERROR Sug.Test - ERROR MESSAGE
 in /usr/local/share/log4php/appenders/LoggerAppenderPhp.php on line 76

어?3건 밖에 나오지 않는다....이것은 trigger_error() 의 사양으로,E_USER_ERROR 그리고 불렸을 경우에는, 「실행을 중지한다」라고 하는 디폴트의 에러 핸들러가 기동되는 것으로 있다.물론, 에러 핸들러를 덧쓰기해버리면 이것은 회피할 수 있다.

require_once( '../log4php-0.9/src/log4php/LoggerManager.php' );

# 자기 부담의 에러 핸들러
function myhandler( $level, $mess, $file, $line ) {
    echo "[$level] $message - $file,$line\n";
}

# 에러 핸들러의 등록
set_error_handler( 'myhandler' );

$logger =& LoggerManager::getLogger('Sug.Test');
$logger->info( 'test start' );
$logger->warn( 'Warning Message' );
# 더이상 이것이 걸리지 않는다.
$logger->error( 'ERROR MESSAGE' );
$logger->fatal( 'FATAL MESSAGE' );
echo "test body\n";
$logger->debug( 'only debug' );
$logger->info( 'test end' );

(이)라고 해도 에러 발생 개소의 리포트가

 in /usr/local/share/log4php/appenders/LoggerAppenderPhp.php on line 78

왜냐하면 맞아, 사용할 수 있는 인...

LoggerAppenderSyslog

SyslogAppender(을)를 참조.이것은 유일 능력적으로 Log4J 에 이기고 있는 것일까? 요컨데 PHP 의 syslog() (을)를 부르고,syslog 한다 Appender 이다.Java (은)는 플랫폼·인디펜던트를 구가하고 있으므로,OS 의존의 syslog(2) (은)는 사용하지 못하고, 그 대신에 UDP 그리고 리모트 로그 서버에 넷 넘어로 전달하는 것만으로 있다(그쪽이 플랫폼 독립인 것은 무엇인가 모순되고 있는 것 같은...).하지만,PHP하 PHP 의 함수의 옆에서 native code 서포트를 해 버린다 (뜻)이유로, 당당히 로컬 syslog (을)를 할 수 있다 syslog() (을)를 가지고 있다.그것을 이것은 사용한다.

옵션은 다음과 같이.특히 아무것도 필요 없다.

layout
불요
Threshold
레벨을 지정해, 그 레벨 이하라고 출력하지 않게 하는 반응을 일으키는 최소의 물리량.모든 Appender 의 공통 옵션.

그리고,log4php 의 로그 레벨과syslog 의 에러 레벨과의 대응 관계는 이러하다.

log4php syslog
DEBUG LOG_DEBUG
INFO LOG_INFO
WARN LOG_WARNING
ERROR LOG_ERR
FATAL LOG_ALERT

그리고, 실제의 로그가 어떻게 될까...에 대해서는,UNIX 계의 경우는,SyslogAppender 에 써 있으므로, 그쪽을 봐 줘.그리고,Windows 의 경우는, 이것이 실질상 NTEventLogAppender (이)라고 같은 것이 된다.

실제로 로그에 나오는 것은, 로그 메세지만으로, 나머지는 완전히 syslog 옆의 출력 사양에 따른다.log4J 의 SyslogAppender (와)과 달라, 아무것도 생각하지 않아 좋다.조금 실험해 보았지만,FACILITY 하 LOG_USER (을)를 사용하고 있다.이 근처에 는 syslog() (을)를 openlog() (을)를 사용하지 않고 열렸을 경우의 디폴트의 FACILITY 의 문제이므로, 참고라고 생각했으면 좋겠다(OS의 설정에 따라서 다른 케이스가 있을 수 있다).뭐 노력해 /etc/syslog.conf (을)를 설정하면, 이 로그를 더욱 리모트 로그 서버에 전달하는 것도 가능하기도 하다 (뜻)이유다...

덧붙여서 시스템의 로그 파일에 나오는 내용은 다음과 같이 되었다(필자의 경우!).

Apr  8 18:19:43 bizet php: test start
Apr  8 18:19:43 bizet php: Warning Message
Apr  8 18:19:43 bizet php: only debug
Apr  8 18:19:43 bizet php: test end
Apr  8 18:19:43 bizet php: Another Logger!

요컨데 PHP 의 syslog() 하지만 「php:」라고 하는 프레픽스를 붙여 단지 로그 메세지를 기록할 만한 출력이다.

LoggerAppenderNull

NullAppender(을)를 참조.아무것도 하지 않는다.이것은 완벽하게 Log4J (와)과 기능이 공통된다(쓴웃음).

옵션은 다음과 같이.

layout
불요
Threshold
레벨을 지정해, 그 레벨 이하라고 출력하지 않게 하는 반응을 일으키는 최소의 물리량.모든 Appender 의 공통 옵션.

설정예는 이런 곳에서 있다.

log4php.appender.null=LoggerAppenderNull

log4php.logger.Sug.Test=debug, null
log4php.rootLogger=debug, null

출력은 이렇게 된다.

% php mytest.php
test body  ← 참고를 위해서 echo 그리고 내고 있는 메세지.로그는 아니다.

찬미했으니까.



 

copyright by K.Sugiura, 1996-2006

HTTP/1.1 200 OK Date: Thu, 17 Jan 2008 17:07:05 GMT Server: Apache/2.2.3 (Debian) DAV/2 PHP/5.2.0-8+etch9 mod_ssl/2.2.3 OpenSSL/0.9.8c Content-Length: 0 Keep-Alive: timeout=10, max=50 Connection: Keep-Alive Content-Type: application/x-perl

 

 

Posted by '김용환'
,

php 로깅 관련

svn 2008. 1. 18. 10:59

 

 

marionweb.com에서 퍼옴

 

 

Intentionally throw PHP errors
Written by Marion Consulting   

Error messages are not something that most developers enjoy seeing, but they can be very useful especially when debugging or testing an applications code.  Sometimes we would like throw an error to see how the application behaves and below is an example of how to do just this.

trigger_error

Generates a user-level error/warning/notice message (PHP 4 >= 4.0.1, PHP 5)

bool trigger_error ( string error_msg [, int error_type] )
 

 

error_msg

The designated error message for this error. It's limited to 1024 characters in length. Any additional characters beyond 1024 will be truncated.

error_type

The designated error type for this error. It only works with the E_USER family of constants, and will default to E_USER_NOTICE.

Example usage: trigger_error ('I just threw an error", E_USER_ERROR); 

 

How to use log4php
Written by Marion Consulting   

This is a very basic tutorial on how to implement log4php into your php projects.

Log4php is a port of log4j, which is a very popular logging utility in java.  It works very nice in PHP and makes it very simple to log information in many different formats.  The following should allow you to begin using this new functionality in your applications.  Download the example code at a zip file that is provided in plain text below

Get log4php source from http://www.vxr.it/log4php/download.html

Untar/zip the files into a directory on your webserver machine.  There are many directories inside the archive that you do not need unless you want to look over the examples. 

      //define the following in your application

      define('LOG4PHP_DIR', 'log4php-0.9'); // the name of the log4php directory
        The log4php-<version>/src/log4php directory is the directory the above variable should point to.
     

      define('LOG4PHP_CONFIGURATION','log_configuration.xml');
 
      require_once(LOG4PHP_DIR.'/LoggerManager.php');    

      // You can create new logger managers for each script/function you call so you can determine where the logging is        occuring.  I suggest naming it the same as the script that it is in.
      $logger = & LoggerManager::getLogger('your_log_mgr_name');

      $logger->debug('place a debugging log statement here');
      $logger->info('place a info log statement here');
      $logger->warn('place a warning log statement here');
      $logger->error('place a error log statement here');
      $logger->fatal('place a fatal log statement here');

      LoggerManager::shutdown();

 

 

 

Explanation and Examples of log_configuration.xml

The xml file can be named whatever you wish, you just need to reference the appropriate name in the definition of LOG4PHP_CONFIGURATION above.  The xml below writes a log file to the filesystem for all logged messages (debug to fatal), and it sends an email to the specified email address on any fatal logged error.  The xml can be configured for a number of different formats, but the log file and email are my preferred logging methods.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
    /**
    *  Script: log_configuration.xml
    *  Author: Author <tony [at] marionweb [dot] com>
    *  
    *  Purpose: Setup logging configuration
    *  Creation Date: 1/29/2006
    *  Details:  Currently setup to write to log file for all messages debug -> fatal.  All fatal messages are emailed to site admin.
    */
-->
<log4php:configuration xmlns:log4php="http://www.vxr.it/log4php/" threshold="all" debug="false">
    <appender name="write_to_log" class="LoggerAppenderDailyFile">
        <param name="datePattern" value="Ymd" />
        <param name="file" value="/path_to_logfile/logs/web_application_%s.log" />
        <layout class="LoggerLayoutTTCC">
            <param name="threadPrinting" value="true" />
            <param name="categoryPrefixing" value="true" />
            <param name="contextPrinting" value="true" />
            <param name="microSecondsPrinting" value="true" />
        </layout>
    </appender>
    <appender name="email_log" class="LoggerAppenderMailEvent">
        <param name="from" value=" admin@email.com" />
        <param name="to" value=" admin@email.com" />
        <param name="subject" value="Log4php test" />
        <layout class="LoggerLayoutTTCC" />
    </appender>
    <root>
        <level value="debug" />       
        <appender_ref ref="write_to_log" />
    </root>
    <root>
        <level value="fatal" />       
        <appender_ref ref="email_log" />
    </root>
</log4php:configuration>

Posted by '김용환'
,

9.2. Manipulating Strings

Bash supports a surprising number of string manipulation operations. Unfortunately, these tools lack a unified focus. Some are a subset of parameter substitution, and others fall under the functionality of the UNIX expr command. This results in inconsistent command syntax and overlap of functionality, not to mention confusion.

String Length

${#string}

expr length $string

expr "$string" : '.*'

   1 stringZ=abcABC123ABCabc
   2 
   3 echo ${#stringZ}                 # 15
   4 echo `expr length $stringZ`      # 15
   5 echo `expr "$stringZ" : '.*'`    # 15


Example 9-10. Inserting a blank line between paragraphs in a text file

   1 #!/bin/bash
   2 # paragraph-space.sh
   3 
   4 # Inserts a blank line between paragraphs of a single-spaced text file.
   5 # Usage: $0 <FILENAME
   6 
   7 MINLEN=45        # May need to change this value.
   8 #  Assume lines shorter than $MINLEN characters
   9 #+ terminate a paragraph.
  10 
  11 while read line  # For as many lines as the input file has...
  12 do
  13   echo "$line"   # Output the line itself.
  14 
  15   len=${#line}
  16   if [ "$len" -lt "$MINLEN" ]
  17     then echo    # Add a blank line after short line.
  18   fi  
  19 done
  20 
  21 exit 0

Length of Matching Substring at Beginning of String

expr match "$string" '$substring'

$substring is a regular expression.

expr "$string" : '$substring'

$substring is a regular expression.

   1 stringZ=abcABC123ABCabc
   2 #       |------|
   3 
   4 echo `expr match "$stringZ" 'abc[A-Z]*.2'`   # 8
   5 echo `expr "$stringZ" : 'abc[A-Z]*.2'`       # 8

Index

expr index $string $substring

Numerical position in $string of first character in $substring that matches.

   1 stringZ=abcABC123ABCabc
   2 echo `expr index "$stringZ" C12`             # 6
   3                                              # C position.
   4 
   5 echo `expr index "$stringZ" 1c`              # 3
   6 # 'c' (in #3 position) matches before '1'.

This is the near equivalent of strchr() in C.

Substring Extraction

${string:position}

Extracts substring from $string at $position.

If the $string parameter is "*" or "@", then this extracts the positional parameters, [1] starting at $position.

${string:position:length}

Extracts $length characters of substring from $string at $position.

   1 stringZ=abcABC123ABCabc
   2 #       0123456789.....
   3 #       0-based indexing.
   4 
   5 echo ${stringZ:0}                            # abcABC123ABCabc
   6 echo ${stringZ:1}                            # bcABC123ABCabc
   7 echo ${stringZ:7}                            # 23ABCabc
   8 
   9 echo ${stringZ:7:3}                          # 23A
  10                                              # Three characters of substring.

If the $string parameter is "*" or "@", then this extracts a maximum of $length positional parameters, starting at $position.

   1 echo ${*:2}          # Echoes second and following positional parameters.
   2 echo ${@:2}          # Same as above.
   3 
   4 echo ${*:2:3}        # Echoes three positional parameters, starting at second.

expr substr $string $position $length

Extracts $length characters from $string starting at $position.

   1 stringZ=abcABC123ABCabc
   2 #       123456789......
   3 #       1-based indexing.
   4 
   5 echo `expr substr $stringZ 1 2`              # ab
   6 echo `expr substr $stringZ 4 3`              # ABC

expr match "$string" '\($substring\)'

Extracts $substring at beginning of $string, where $substring is a regular expression.

expr "$string" : '\($substring\)'

Extracts $substring at beginning of $string, where $substring is a regular expression.

   1 stringZ=abcABC123ABCabc
   2 #       =======	    
   3 
   4 echo `expr match "$stringZ" '\(.[b-c]*[A-Z]..[0-9]\)'`   # abcABC1
   5 echo `expr "$stringZ" : '\(.[b-c]*[A-Z]..[0-9]\)'`       # abcABC1
   6 echo `expr "$stringZ" : '\(.......\)'`                   # abcABC1
   7 # All of the above forms give an identical result.

expr match "$string" '.*\($substring\)'

Extracts $substring at end of $string, where $substring is a regular expression.

expr "$string" : '.*\($substring\)'

Extracts $substring at end of $string, where $substring is a regular expression.

   1 stringZ=abcABC123ABCabc
   2 #                ======
   3 
   4 echo `expr match "$stringZ" '.*\([A-C][A-C][A-C][a-c]*\)'`    # ABCabc
   5 echo `expr "$stringZ" : '.*\(......\)'`                       # ABCabc

Substring Removal

${string#substring}

Strips shortest match of $substring from front of $string.

${string##substring}

Strips longest match of $substring from front of $string.

   1 stringZ=abcABC123ABCabc
   2 #       |----|
   3 #       |----------|
   4 
   5 echo ${stringZ#a*C}      # 123ABCabc
   6 # Strip out shortest match between 'a' and 'C'.
   7 
   8 echo ${stringZ##a*C}     # abc
   9 # Strip out longest match between 'a' and 'C'.

${string%substring}

Strips shortest match of $substring from back of $string.

${string%%substring}

Strips longest match of $substring from back of $string.

   1 stringZ=abcABC123ABCabc
   2 #                    ||
   3 #        |------------|
   4 
   5 echo ${stringZ%b*c}      # abcABC123ABCa
   6 # Strip out shortest match between 'b' and 'c', from back of $stringZ.
   7 
   8 echo ${stringZ%%b*c}     # a
   9 # Strip out longest match between 'b' and 'c', from back of $stringZ.


Example 9-11. Converting graphic file formats, with filename change

   1 #!/bin/bash
   2 #  cvt.sh:
   3 #  Converts all the MacPaint image files in a directory to "pbm" format.
   4 
   5 #  Uses the "macptopbm" binary from the "netpbm" package,
   6 #+ which is maintained by Brian Henderson (bryanh@giraffe-data.com).
   7 #  Netpbm is a standard part of most Linux distros.
   8 
   9 OPERATION=macptopbm
  10 SUFFIX=pbm          # New filename suffix. 
  11 
  12 if [ -n "$1" ]
  13 then
  14   directory=$1      # If directory name given as a script argument...
  15 else
  16   directory=$PWD    # Otherwise use current working directory.
  17 fi  
  18   
  19 #  Assumes all files in the target directory are MacPaint image files,
  20 # + with a ".mac" suffix.
  21 
  22 for file in $directory/*    # Filename globbing.
  23 do
  24   filename=${file%.*c}      #  Strip ".mac" suffix off filename
  25                             #+ ('.*c' matches everything
  26 			    #+ between '.' and 'c', inclusive).
  27   $OPERATION $file > "$filename.$SUFFIX"
  28                             # Redirect conversion to new filename.
  29   rm -f $file               # Delete original files after converting.   
  30   echo "$filename.$SUFFIX"  # Log what is happening to stdout.
  31 done
  32 
  33 exit 0
  34 
  35 # Exercise:
  36 # --------
  37 #  As it stands, this script converts *all* the files in the current
  38 #+ working directory.
  39 #  Modify it to work *only* on files with a ".mac" suffix.

Substring Replacement

${string/substring/replacement}

Replace first match of $substring with $replacement.

${string//substring/replacement}

Replace all matches of $substring with $replacement.

   1 stringZ=abcABC123ABCabc
   2 
   3 echo ${stringZ/abc/xyz}           # xyzABC123ABCabc
   4                                   # Replaces first match of 'abc' with 'xyz'.
   5 
   6 echo ${stringZ//abc/xyz}          # xyzABC123ABCxyz
   7                                   # Replaces all matches of 'abc' with # 'xyz'.

${string/#substring/replacement}

If $substring matches front end of $string, substitute $replacement for $substring.

${string/%substring/replacement}

If $substring matches back end of $string, substitute $replacement for $substring.

   1 stringZ=abcABC123ABCabc
   2 
   3 echo ${stringZ/#abc/XYZ}          # XYZABC123ABCabc
   4                                   # Replaces front-end match of 'abc' with 'XYZ'.
   5 
   6 echo ${stringZ/%abc/XYZ}          # abcABC123ABCXYZ
   7                                   # Replaces back-end match of 'abc' with 'XYZ'.

9.2.1. Manipulating strings using awk

A Bash script may invoke the string manipulation facilities of awk as an alternative to using its built-in operations.


Example 9-12. Alternate ways of extracting substrings

   1 #!/bin/bash
   2 # substring-extraction.sh
   3 
   4 String=23skidoo1
   5 #      012345678    Bash
   6 #      123456789    awk
   7 # Note different string indexing system:
   8 # Bash numbers first character of string as '0'.
   9 # Awk  numbers first character of string as '1'.
  10 
  11 echo ${String:2:4} # position 3 (0-1-2), 4 characters long
  12                                          # skid
  13 
  14 # The awk equivalent of ${string:pos:length} is substr(string,pos,length).
  15 echo | awk '
  16 { print substr("'"${String}"'",3,4)      # skid
  17 }
  18 '
  19 #  Piping an empty "echo" to awk gives it dummy input,
  20 #+ and thus makes it unnecessary to supply a filename.
  21 
  22 exit 0

9.2.2. Further Discussion

For more on string manipulation in scripts, refer to Section 9.3 and the relevant section of the expr command listing. For script examples, see:

  1. Example 12-6

  2. Example 9-15

  3. Example 9-16

  4. Example 9-17

  5. Example 9-19

Notes

[1]

This applies to either command line arguments or parameters passed to a function.

'unix and linux' 카테고리의 다른 글

Redhat 리눅스 버젼 보기  (0) 2008.03.28
Why I love Perl  (0) 2008.02.20
고급 Bash 스크립팅 가이드  (0) 2008.01.18
rotatelog.c 버그 수정해놓기  (0) 2008.01.16
getopt() 함수  (0) 2008.01.16
Posted by '김용환'
,

Bash Shell and Beyond

By William Park

Series Introduction

In this monthly series, I will try to expose the power of the Bash shell. In particular, the readers will be introduced to Bash.Diff which is a collection of my patches incorporating many ideas from Ksh, Zsh, Awk, Python, and other languages.

Each article will focus on one theme or feature, which is not normally thought of in shell context. I will also make liberal use of shell functions, standard builtins, dynamically loadable builtins, and advanced features patched into Bash, in a format that can be easily sourced and maintained.

string.sh

In C, <string.h> defines strcat(3), strcpy(3), strlen(3), and strcmp(3) for string concatenation, copy, size, and test operations respectively. Such basic operations are needed constantly when programming in any language, and shell scripting is no exception.

strcat() and strcpy()

For string copy and concatenation, you would do something like
    a=abc
    a=${a}'123'			# a=abc123
in shell. This is simple variable assignment. However, you can't have variable reference on the left-hand side (LHS) of '='. You have to either type the LHS variable name explicitly as above, or use eval, as in
    x=a
    eval "$x=abc"
    eval "$x=\${$x}'123'"
to parse the "..." expressions twice. It quickly becomes painful to call eval all the time, especially when the variable names are parsed from a file or a string.

What is needed is a shell version of C functions strcat(3) and strcpy(3) which can be called with equal ease and simplicity. So, here they are:

    strcat ()		# var+=string
    {
	local _VAR=$1 _STRING=$2 _a _b

	case $#.$3 in
	    2.) ;;
	    3.*:*) _a=${3%:*} _b=${3#*:}
		set -- `python_to_shell_range "$_a" "$_b" ${#_STRING}`
		_STRING=${_STRING:$1:$2}
		;;
	    *)  echo "Usage: strcat var string [a:b]"
		return 2
		;;
	esac
	eval "$_VAR=\${$_VAR}\$_STRING"
    }

    strcpy ()		# var=string
    {
	local _VAR=$1 _STRING=$2 _a _b

	case $#.$3 in
	    2.) ;;
	    3.*:*) _a=${3%:*} _b=${3#*:}
		set -- `python_to_shell_range "$_a" "$_b" ${#_STRING}`
		_STRING=${_STRING:$1:$2}
		;;
	    *)  echo "Usage: strcpy var string [a:b]"
		return 2
		;;
	esac
	eval "$_VAR=\$_STRING"
    }
where 'var' is the name of variable you want to use to store the result. The above example, then, becomes
    x=a
    strcpy $x abc		# a=abc
    strcat $x 123		# a+=123

strlen()

In C, strlen(3) gives you the size of a string. In the shell, you would use parameter expansion (i.e., ${#var}):

    a=abc123
    echo ${#a}			# 6
Here is a shell version of C function strlen(3):
    strlen ()		# echo ${#string} ...
    {
	for i in "$@"; do
	    echo ${#i}
	done
    }
which has the additional ability of accepting multiple strings, e.g.
    strlen abc123 0123456789		# 6 10

strcmp()

To compare two strings for equality, you use strcmp(3) in C. In shell, you would do something like

    [ $a = abc123 ]
Here is a shell version of C function strcmp(3):
    strcmp ()		# string == string
    {
	local _STRING1=$1 _STRING2=$2 _a _b
      
	case $#.$3 in
	    2.) ;;
	    3.*:*) _a=${3%:*} _b=${3#*:}
		set -- `python_to_shell_range "$_a" "$_b" ${#_STRING1}`
		_STRING1=${_STRING1:$1:$2}
		set -- `python_to_shell_range "$_a" "$_b" ${#_STRING2}`
		_STRING2=${_STRING2:$1:$2}
		;;
	    *)  echo "Usage: strcmp string1 string2 [a:b]"
		return 2
		;;
	esac
	[ "$_STRING1" == "$_STRING2" ]
    }
so that the above example becomes
    strcmp $a abc123

Python-style [a:b] substring

Extracting substrings is another common operation. In the shell, you would use parameter expansion (i.e., ${var:a:n}), where 'a' is starting index and 'n' is the number of characters to extract. So,

    b=0123456789
    echo ${b:0:3} ${b: -3} ${b:1:${#b}-2}
will print the first 3 chars, the last 3 chars, and all chars except the first and the last, respectively.

The main problem with this syntax is that 'n' is a relative number starting at index 'a'. Usually, absolute index is more convenient, not only because it's more natural, but also because that's the way it is in C. Python has syntax var[a:b], where 'a' and 'b' are indexes which can be positive, negative, or omitted. Although it's roughly equivalent to ${var:a:b-a} in shell, missing 'a' and 'b' means the beginning and the end of string, and negative index means offset from the end of string.

The above shell functions strcat(), strcpy(), and strcmp() already support Python-style [a:b] format, provided you source an internal function.

    # string[a:b] --> ${string:a:n}
    #
    # Convert Python-style string[a:b] range into Shell-style ${string:a:n} range,
    # where
    #	0 <= a <= b <= size  and  a + n = b
    #
    python_to_shell_range ()
    {
	local -i size=$3
	local -i b=${2:-$size}
	local -i a=${1:-0}

	if [ $# -ne 3 ]; then
	    echo "Usage: python_to_shell_range a b size"
	    return 2
	fi

	[[ a -lt 0 ]] && a=$((a+size))
	[[ a -lt 0 ]] && a=0
	[[ a -gt size ]] && a=$size

	[[ b -lt 0 ]] && b=$((b+size))
	[[ b -lt 0 ]] && b=0
	[[ b -gt size ]] && b=$size
	[[ b -lt a ]] && b=$a

	echo $a $((b-a))
    }
to convert Python range to shell range. It's not user-serviceable, but you can try it out:
    python_to_shell_range '' 3 10		# 0 3
    python_to_shell_range -3 '' 10		# 7 3
    python_to_shell_range 1 -1 10		# 1 8
Now, you can specify a substring for strcat(), strcpy(), and strcmp() using Python-style [a:b] range as the third parameter, like this:
    b=0123456789
    strcpy x $b :3		# x=012
    strcpy y $b -3:		# y=789
    strcpy z $b 1:-1		# z=12345678
    echo $x $y $z

Chaining of tests

strcmp() tests two strings for equality. When there is a chain of 2 or more binary tests, like 'a < c > b' or '1 -lt 3 -gt 2', you have to break it up and test each pair:

    [[ a < c ]] && [[ c > b ]]
    [ 1 -lt 3 ] && [ 3 -gt 2 ]
This breaks up the flow of your code, not to mention being error-prone. Here is a shell function which enables you to simply write down the chains on command-line:
    testchain ()		# string OP string OP string ...
    {
	if [ $# -lt 3 ]; then
	    echo "Usage: testchain string OP string [OP string ...]"
	    return 2
	fi
	while [ $# -ge 3 ]; do
	    test "$1" "$2" "$3" || return 1
	    shift 2
	done
    }
where 'OP' is any binary operator accepted by test command. You use it much like test command:
    testchain a '<' c '>' b
    testchain 1 -lt 3 -gt 2

Summary

The source code for the 6 shell functions listed in this article is also available from string.sh. To use it, just source it,
    . string.sh
In the next article, we'll see how strcat(), strcpy(), strlen(), and strcmp() shell functions can be written in C and compiled as builtin commands. And that will be the first introduction to my patched Bash shell. :-)

 

Posted by '김용환'
,