กำจัด จุดอ่อนของ perl

Filed under เรื่อยเปื่อย บ่นๆ ไร้สาระมั่ง ไม่ไร้สาระมั่ง
Tagged as

ความที่ ผมเขียน perl มานาน (จริงๆ คือ ถนัดและเขียนเป็นอยู่ภาษาเดียว ^^”)
และ เจ้าภาษา perl มันมีปัญหา ให้ปวดตับ อยู่ 1 อย่างคือ เรื่องการ ซด RAM (สามารถแดกได้ 2GB ในไม่กี่ ชม. – -”)

หลักๆ ที่เห็นชัดๆ ก็ประมาณว่า สคิปไหนที่ต้องทำงานตลอดเวลา
สคิปเจ้ากรรม มันจะ ซด RAM แบบ ซดไปเรื่อยๆ
จากที่สังเกตุคือ เมื่อมีการ ประกาศ ตัวแปรอะไรเพิ่ม หรือ มีค่าอะไรเข้าไปใน ตัวแปร
สคิปมันก็จะเอา RAM จาก OS ไปใช้ … แล้วเมื่อมันทำงานเสร็จ
ไม่ว่าจะ undef, delete, flush ตัวแปรนั้นๆ … สคิปมันก็จะไม่คืน RAM ที่มันจองไปให้ตัวแปรต่างๆ ให้ OS หลักซะงั้น !!

ซึ่ง ผมค่อนข้างมั่นใจว่า ผมงมหาวิธีแก้เรื่องนี้มานานมากกกกกกกกกก จนยอมแพ้และเริ่มทำใจยอมรับมัน
(ถ้าจำไม่ผิด ผมหาวิธีแก้ไขเรื่องการซด ram ของ perl แบบตั้งใจสุดๆ ไป ราวๆ 3 รอบ)

ในที่สุดวันนี้ ระหว่างรื้อ บอท iRC มานั่งเขียนใหม่ โดยกะใช้ thread เพื่อ ทำ multi process
ด้วยความคิดชั่วร้ายว่า ต้องเริ่มเปิดคลังแสง มาไล่เก็บ server ใหม่อีกซักรอบ
ซึ่งก็เจอปัญหาเดิมคือ .. พอเริ่มรัน บอทจะ กิน ram ราวๆ 6Mb .. แต่พอสั่งทำงาน มันกิน ram ไปเรื่อยๆ process ละ 6Mb !!
ซึ่ง ถ้าตู แฮกเครื่องชาวบ้านมารันบอท .. ไม่ว่าจะสั่งหรือไม่สั่ง ให้บอททำงาน
ก็ดูแล้วไม่น่า เกิน 1 วัน โดน host เตะ ข้อหาซด ram หมด แน่นอน

ก็เลย ไปงม วิธีแก้ไขใหม่ .. และ ก็ข้องใจอยู่ในหัวสมองน้อยๆ ว่า “เอ๊ะ ทำไม สคิปบอท โบราณมันถึงทำงานได้ไม่มีปัญหากันฟ๊ะ”

และในที่สุด ผมก็ไปเจอ ฝรั่ง comment ไว้แนวๆ เดิม คือ ไม่ว่ามึงจะทำไง perl ก็ไม่คือน ram ให้ OS หร๊อก บลาๆ ๆ
(ลอง ค้นๆ ดูเลย มั่นใจว่าจะเจอแต่ comment แนวๆ นี้จริงๆ และ ผมทดสอบแล้ว มันก็เป็นจริงๆ อย่างที่ฝรั่ง มันว่า นะ)

แต่ ไปเจอ อยู่ comment หนึ่งบอกว่า ให้ ใช้ fork แยกไปทำงาน .. และเมื่อ exit ปุ๊ป ram ที่ fork ดึงไป มันจะหายไป !!
เหยดดดดดดดด … นี่ล่ะ คำตอบ ที่ต้องการ

สรุปก็คือ
หากเรา เขียน perl ให้ใช้ thread
เมื่อ แตก thread ลูก ออกมา และ process ลูกเริ่มทำงาน process ลูกก็จะ ดึง ram จาก OS ไปใช้
ซึ่ง ram ทั้งหมดที่ใช้ มันก็จะมารวมอยู่ ใน process หลัก นั่นเอง
และเมื่อ process ลูกทำงานเสร็จ และ detach ตัวมันหายไป … มันเสือกหายไปแต่ process ลูก
แต่อี process แม่ ยัง อม ram ที่จองมา ไว้เหมือนเดิม !!
แล้วพอ แตก process ลูกไปทำงานชิ้นใหม่ .. มันก็ ขอ ram เพิ่มจาก OS อีก .. ทำให้ มัน จอง ram ไปเรื่อยๆๆ ๆ ๆ ๆ ๆ

แต่หากใช้ fork
มันจะ แตก process ออกมาเป็น อีก PID เลย .. ซึ่งมันก็จะ ดึง ram จาก OS มาใช้ของมันไป ตามเรื่องของมัน
และ เมื่อ ทำงานเสร็จ พอเรา exit ตัว PID ของ process ที่ fork ออกมา .. ram ที่ใช้ ก็จะหายไปคืนกลับ ให้ OS
เหมือนเราปิด โปรแกรม ไปแล้วนั่นเอง

เหยดดดดดดดดดดดดดดดดดดดดดดดดดดดด … และแล้วก็ ถึงเวลา เดือดร้อนชาวโลก อีกแล้ว ซินะ !!!

ปล. กลับไปรัก fork เหมือนเดิม

edit
จริงๆแล้ว thread มีข้อดีคือ สามารถ แชร์ $variable ได้
แต่ fork แชร์ไม่ได้ (เพราะ มันแยก process มาทำงาน … เหมือนเรา เปิด โปรแกรมคนละตัว)

แถมบทความ 90% ที่จะให้ fork แชร์ variable ข้าม process ได้
ก็คือ ให้ใช้ IPC เป็นตัวจัดการ เก็บ variable เข้าไป ใน ram แล้ว process ตัวอื่นๆ ค่อยดึงออกมา
แต่ รู้ไว้ซะว่า IPC นั่น last update มันปี 2001 ว่ะ .. มันใช้กับ perl 5.8 ไม่ได้
… ไอ้ห่ารากกกกกกกกก มึงจะแนะนำใหม่กว่านี้ไม่ได้ใช่มั้ย !!

จริงๆแล้ว ถ้าเขียนลง ram ไม่ได้ ก็แก้โดย เขียนเก็บมันใน file
แล้วให้ process อื่นมาเปิดอ่านเอาโลด (แก้ปัญหา แบบ เขียน ง่ายๆ เลย อิอิ)

[perl] Add New VirtualHost for Blackbuntu

Filed under รวม code ทั้งมั่วเอง ทั้งจิ๊กชาวบ้านมา
Tagged as
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!/usr/bin/perl -w
##########
# Command
# sudo echo ${SITE}>>/etc/hosts
# <create /etc/apache2/sites-available/${SITE}>
# sudo a2ensite ${SITE}
# sudo /etc/init.d/apache2 restart
#
# *This file need root
 
my $SITE = $ARGV[0];
my $USER = 'unknown';
my $PATH = '/home/'.$USER.'/www/';
 
if(!$SITE){
  print "[+] Input Site Name:";
  chomp ($SITE = <>);
}
 
my $FOLDER = $PATH.$SITE;
if(-d $FOLDER){
  die "$FOLDER exists\n" 
}else{
  my $step_1_create_folder = `mkdir $FOLDER && chown $USER:$USER $FOLDER`;
}
 
 
my $step_2 = `echo 127.0.0.1\t${SITE}>>/etc/hosts`;
my $step_3 = &write_file('/etc/apache2/sites-available/site.'.$SITE, make_file($PATH, $SITE));
my $step_4 = `a2ensite site.${SITE} && /etc/init.d/apache2 restart`;
 
 
 
sub make_file {
  return '<VirtualHost *:80>
  ServerName '.$_[1].'
	ServerAlias '.$_[1].' *.'.$_[1].'
	ServerAdmin admin@stephack.com
	DocumentRoot '.$_[0].$_[1].'
	<Directory />
		Options FollowSymLinks
		AllowOverride All
	</Directory>
	<Directory '.$_[0].$_[1].'/>
		Options Indexes FollowSymLinks MultiViews
		AllowOverride All
		Order allow,deny
		allow from all
	</Directory>
 
	ErrorLog '.$_[0].'error.log
	CustomLog '.$_[0].'access.log combined
</VirtualHost>
';
}
 
sub write_file {
  my $file = $_[0];
  my $content = $_[1];  
  open F, "> $file" or die "Can't open $file : $!";
  print F $content;
  close F;
}

การ ใช้ Authenticate ใน PHP กรณี safemode = On

Filed under เรื่อยเปื่อย บ่นๆ ไร้สาระมั่ง ไม่ไร้สาระมั่ง

กรณีที่ ตั้งค่า safemode เป็น On
ค่าจาก $_SERVER['PHP_AUTH_USER'] และ $_SERVER['PHP_AUTH_PW'] จะไม่สามารถ เรียกใช้งานได้
ดังนั้น การเขียน ให้ login ผ่าน WWW-Authenticate ก็จะไม่ทำงาน (ผมก็งม อยู่ตั้งนาน)

วิธีแก้ คือ

สร้าง .htaccess ขึ้นมา
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
</IfModule>

เพิ่ม
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
ลงไป ใน script

ก็จะเป็น ประมาณ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?
$auth = 1; //Auth on/off == 1/0
$namelogin="root";//login = "root"
$passlogin="63a9f0ea7bb98050796b649e85481845";//pass  = "root"
 
if($auth == 1){
  list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
  if(!isset($_SERVER['PHP_AUTH_USER']) ||
    ($_SERVER['PHP_AUTH_USER'] != $namelogin) ||
    (md5($_SERVER['PHP_AUTH_PW']) != $passlogin)
  ){
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Basic realm="Authentication Zone"');
    exit('wtf?');
  }
}
?>