debian: ติดตั้ง samba

เอามาจาก ThaiLinuxCafe - debian : ติดตั้ง samba อย่างง่าย

โครงร่างคือ

ชื่อเซิร์ฟเวอร์
server1 : 192.168.1.5
แชร์ที่อ่านได้อย่างเดียว
//server1/app จะให้อยู่ที่ /samba/app ( เพื่อเร่งความเร็วและป้องกันไวรัส )
แชร์ที่อ่าน/เขียนได้
//server1/data จะให้อยู่ที่ /samba/data
ชื่อ Workgroup
smbdomain
กรุ๊ปที่มีสิทธิ์ใช้งาน
smbgroup ให้มี gid=1001
ผู้ใช้ที่มีสิทธิ์ใช้งาน
user1, user2, user3, ... ให้มี uid=1101, 1102, 1103, ...
ผู้ควบคุมระบบ
smb-admin ให้มี uid=1100
เครื่องลูกข่าย
client01, client02, ... ให้มีไอพีเป็น 192.168.1.101, 192.168.1.102, ...

เริ่มด้วย

ที่เซิร์ฟเวอร์

ติดตั้ง samba
# aptitude install samba

Workgroup/Domain Name:
<<<--- smbdomain

Modify smb.conf to use WINS settings from DHCP?
<<<--- No

เพิ่มกรุ๊ปในการใช้งาน samba
# groupadd -g 1001 smbgroup

สร้างสคริปต์ในการเพิ่มผู้ใช้ ให้มีรหัสผ่านเดียวกัน (passwd กับ smbpasswd) ตั้งชื่อว่า d.addsmb
# vi /usr/local/bin/d.smbadd

#!/bin/bash
if [ ! $3 ]; then
  echo "Usage: $0 USERNAME UID PASSWORD"
  exit 1;
fi
GROUPNAME="smbgroup"
USERNAME=$1
USERID=$2
PASSWORD=$3
/usr/sbin/useradd -g $GROUPNAME -u $USERID -m $USERNAME
echo "$USERNAME:$PASSWORD" | /usr/sbin/chpasswd
(echo "$PASSWORD"; echo "$PASSWORD") | smbpasswd -a -s $USERNAME
echo "User: $USERNAME , uid: $USERID added."

เวลาเพิ่มผู้ใช้ก็สั่ง
# d.smbadd user1 1101 USER1-PASSWORD
...

ทำไปจนครบผู้ใช้

เพิ่มผู้ใช้ของ samba ที่เป็นผู้คุมระบบ ให้ชื่อว่า smb-admin
# d.smbadd smb-admin 1100 SMB-ADMIN-PASSWORD

สร้างไดเรคทอรี่สำหรับแชร์ไฟล์ ตั้งชื่อว่า /samba
# mkdir -p /samba/app
# mkdir -p /samba/data

เปลี่ยนสิทธิ์การใช้งานไดเรคทอรี่ samba
# chown -R smb-admin:smbgroup /samba
# chmod 0750 /samba/app
# chmod 0770 /samba/data

ตั้งค่าการใช้งานให้ samba
# vi /etc/samba/smb.conf
เฉพาะค่าที่เราจะเปลี่ยนแปลง

[global]
    workgroup = smbdomain
    security = user
    unix charset = utf8
    display charset = utf8
    lock spin time = 15        ;; for dbase/foxpro record lock
    lock spin count = 30      ;; for dbase/foxpro record lock
    unix extensions = yes

[app]
    comment = Application Dir
    path = /samba/app
    valid users = @smbgroup
    admin users = smb-admin
    public = no
    create mask = 0750
    directory mask = 0750
    fake oplocks = yes        ;; increase speed
    writable = no

[data]
    comment = Data Dir
    path = /samba/data
    valid users = @smbgroup
    public = no
    create mask = 0770
    directory mask = 0770
    writable = yes

แก้ไขไฟล์ hosts ให้เครื่องลูกข่ายติดต่อได้
# vi /etc/hosts

192.168.1.1      server1.example.com    server1
192.168.1.101    client01.example.com    client01
192.168.1.102    client02.example.com    client02
192.168.1.103    client03.example.com    client03
...

เริ่มการทำงาน samba ใหม่
# /etc/init.d/samba restart


ส่วนของเครื่องลูกข่าย

เรียกใช้งานจากลินุกส์

ติดตั้ง smbclient
# aptitude install smbclient smbfs

สร้างจุดเมาต์
# mkdir -p /mnt/app
# mkdir -p /mnt/data

แก้ไขข้อมูล hosts ให้เหมือนกับที่เครื่อง server1
# vi /etc/hosts

192.168.1.1      server1.example.com    server1
192.168.1.101    client01.example.com    client01
192.168.1.102    client02.example.com    client02
192.168.1.103    client03.example.com    client03
...

ทำการเมาต์
- การเมาต์แบบ cifs จะทำให้การแสดงชื่อไฟล์เป็นภาษาไทยได้อย่างถูกต้อง
$ sudo mount -t cifs -o username=user1,password=PASSWORD,iocharset=utf8 //server1/app /mnt/app
$ sudo mount -t cifs -o username=user1,password=PASSWORD,iocharset=utf8 //server1/data /mnt/data

- หรือเมาต์แบบ smbfs จะทำให้การล๊อกเรคคอร์ดของโปรแกรมฐานข้อมูลบนไฟล์ แบบ access,dbase,foxpro
ทำงานถูกต้อง
$ sudo mkdir -p /mnt/smbfs/app
$ sudo mkdir -p /mnt/smbfs/data
$ sudo mount -t smbfs -o username=user1,password=PASSWORD,uid=1101,gid=1001 //server1/app /mnt/smbfs/app
$ sudo mount -t smbfs -o username=user1,password=PASSWORD,uid=1101,gid=1001 //server1/data /mnt/smbfs/data

เราสามารถใช้งานไฟล์เซิร์ฟเวอร์ server1 ได้จากจุดเมาต์ /mnt/app และ /mnt/data ตามต้องการ
( ถ้าจะเขียนลง /mnt/app ให้ใช้ชื่อเป็น smb-admin จึงจะสามารถเขียนได้ )

update 50-10-20
ตอนที่ทดลองนี้ cifs บนเดเบียน sid (samba-3.0.26a-1) แก้ปัญหาเรื่องแคชไม่ตรง และล๊อกเรคคอร์ดช้าได้แล้ว
โดยการแก้ไขไฟล์ smb.ini ในหมวด share ให้มีพารามิเตอร์คือ

[data]
    ...
    strict locking = yes
    oplocks = yes
    level2 oplocks = no
    ...

และเมานต์ด้วยพารามิเตอร์ directio เช่น
$ sudo mount -t cifs //server1/data /mnt/smbfs/data -o username=USER,password=PASSWORD,iocharset=utf8,directio

จะสามารถล๊อกเรคคอร์ดได้ตรงและแก้ปัญหาแคชไฟล์ได้แล้วครับ
*****

เรียกใช้งานจาก Windows98/Me

ที่เครื่อง client01 ติดตั้งโดย
Start -> Control Panel -> Network

[TAB] Configuration :
    TCP/IP -> การ์ดไดร์ฟเวอร์ : Properties
        [TAB] DNS Configuration :
            Enable DNS
            DNS Server Search Order : 192.168.1.5
            Domain Suffix Search Order : server1.example.com
        [TAB] IP Address
            Specify an IP address : 192.168.1.101
            Subnet Mask : 255.255.255.0
[TAB]Identification : Workgroup = smbdomain

เรียกใช้งานโดย
คลิกขวา Network Neighbourhood
Map Network Drive
Drive : I:
Path : \\server1\app

เกร็ดเพิ่มเติม

พิมพ์จากดอสใน WinXP
  • คำสั่งคือ
    net use lpt1: \\server\share
  • แก้ปัญหาพิมพ์ช้า ต้องแก้ที่ registry
    Start -> run -> regedit
    HKEY_LOCAL_MACHINE -> SYSTEM -> CurrentControlSet -> Control -&gt WOW
    LPT_Timeout = 1

    เอามาจาก Printing delays from DOS apps under Windows

Topic: 

บันทึกติดตั้ง swat

swat เป็นเครื่องมือจัดการแก้ไขไฟล์คอนฟิกของ samba ผ่านเว็บ

ติดตั้ง swat
# aptitude install swat

เนื่องจาก swat ทำงานผ่าน inetd ซึ่งเดเบียนใช้ openbsd-inetd
จะให้ swat ทำงานได้ ก็ต้องเริ่ม inetd ใหม่
# /etc/init.d/openbsd-inetd restart

ได้แล้ว
สามารถเรียกใช้งานได้จากบราวเซอร์ทั่วไปผ่านพอร์ต 901
http://server1.example.com:901
สามารถใช้สิทธิ์ root ในการล๊อกอินได้เลย

Topic: 

สร้างปรินเตอร์เทียมพิมพ์ลงไฟล์ Tiff

เอามาจาก ThaiLinuxCafe - tip1 : สร้างปรินเตอร์เทียม สำหรับงานพิมพ์ลงไฟล์ (tiff)

โครงร่าง

  • จะให้ปรินเตอร์เทียมตัวนี้ชื่อ PrintToTiff
  • เวลาพิมพ์ งานพิมพ์คือไฟล์ Tiff จะให้ออกมาอยู่ที่ //smbserver/data/PrintToTiff/tif ตัวจริงอยู่ที่ /samba/data/PrintToTiff/tif
    โดยให้บันทึกวันที่เป็นชื่อไฟล์ เพื่อความสะดวกในการค้นหา
  • ไฟล์ข้อมูลบันทึก ( log file ) จะให้อยู่ที่ //smbserver/data/PrintToTiff/log ตัวจริงอยู่ที่ /smba/data/PrintToTiff/log
    โดยจะเก็บการบันทึกไว้เฉพาะการพิมพ์ครั้งล่าสุด ( ขี้เกียจทำ logrotate )

ที่เซิร์ฟเวอร์
สร้างพาธให้ไฟล์ข้อมูล
# mkdir -p /samba/data/PrintToTiff/tif
# mkdir -p /samba/data/PrintToTiff/log

เปลี่ยนสิทธิ์ให้พาธ PrintToTiff
# chown -R user1:smbgroup /samba/data/PrintToTiff
# chmod -R 0777 /samba/data/PrintToTiff

คิดตั้ง ghostscript เพื่อใช้สำหรับแปลงไฟล์ postscript เป็น tiff
# aptitude install gs

แก้ไขไฟล์คอนฟิกของ samba โดยเพิ่มส่วนของพรินเตอร์ PrintToTiff
# vi /etc/samba/smb.conf
เพิ่มเข้าไปต่อท้ายไฟล์

...
[PrintToTiff]
    path = /samba/data/PrintToTiff/tif
    create mask = 0777
    printing = bsd
    printable= yes
    Print command = DATE=`date +%F`;LOG="/samba/data/PrintToTiff/log";gs -dBATCH -sDEVICE=tiffg3 -sOutputFile=/samba/data/PrintToTiff/tif/$DATE-%s.tif %s > $LOG/smb-PrintToTiff.log;rm %s
    valid users = @smbgroup
    public = yes

เริ่ม samba ใหม่
# /etc/init.d/samba restart

เสร็จแล้วครับ

เครื่องลูกข่ายที่เป็น Windows 98/Me
เพิ่มเครื่องพิมพ์ โดยเลือกเป็นเครื่องพิมพ์อะไรก็ได้ ขอให้ใช้ไดร์ฟเวอร์เป็น postscript ก็ใช้ได้
นิยมใช้เป็น Apple LaserWriter
โดยเลือกให้พิมพ์ไปที่ \\smbserver\PrintToTiff

เครื่องลูกข่ายที่เป็นลินุกส์
ติดตั้ง cups
$ sudo aptitude install cupsys-client cupsys-driver-gimpprint cupsys-driver-gimpprint-data

ถ้าเป็นบรรทัดคำสั่งก็ใช้
$ sudo lpadmin -p PrintToTiff -u allow:all -E -v smb://$USER:$PASSWORD@smbserver/PrintToTiff -m ImageWriter.ppd

หรือถ้าเป็น Ubuntu/Gnome ก็ใช้
System -> Administation -> Printing -> New Printer
1.Printer Connection
NetWork Printer -> Windows Printer (SMB)
!!!! Authentication Required
<<<--- Username : user1
<<<--- Password : YOUR-user1-PASSWORD
<<<--- Host : smbserver
<<<--- Printer : PrintToTiff

2.Printer Driver
Apple - Laser Writer IIg

การประยุกต์ใช้งาน
อาจสร้างเป็น FaxIn ไว้เก็บแฟกซ์เข้า
และ FaxOut ไว้เก็บแฟกซ์ที่ส่งออก
หรืออาจเปลี่ยนเอนจินเป็น pdf เพื่อเอาไว้ใช้แปลงเป็น pdf

update
ตัวอย่าง ทำเป็น FaxOut แบบกระจายไปเป็น ปีพ.ศ./เดือน แบบอัตโนมัติ

...
[PrintToTiff]
    path = /samba/data/FaxOut
    create mask = 0777
    printing = bsd
    printable= yes
    Print command = ROOT="/samba/data/FaxOut";MONTH=`date +%m`;let "YEAR=`date +%G` + 543";FAXDIR="$ROOT/$YEAR/$MONTH";mkdir -p $FAXDIR;gs -dBATCH -sDEVICE=tiffg3 -sOutputFile="$FAXDIR/%s.tif %s > $ROOT/lastlog.log;rm %s
    valid users = @smbgroup
    public = yes

samba: ปรับปรุงสร้างปรินเตอร์เทียม

จากคราวก่อนเรื่อง สร้างปรินเตอร์เทียมพิมพ์ลงไฟล์ Tiff
หลังจากเริ่มเอา lenny มาใช้กับเซิร์ฟเวอร์ ผ่านการอัปเกรด/ดาวน์เกรดแพกเกจ samba หลายครั้ง พบว่าปรินเตอร์เริ่มทำงานรวนเร
สุดท้ายกลายเป็นเขียนสคริปต์แยกออกมาดีกว่า สรุปดังนี้คือ
มีปรินเตอร์ 3 ตัว

  1. FaxOut เอาไว้เก็บสำเนาแฟกซ์ส่งออก
  2. FaxIn เอาไว้เก็บสำเนาแฟกซ์เข้า
  3. PrintToPDF เอาไว้เก็บสำเนาแผนที่ (รวมทั้งอาจทำ annotate เพิ่มได้จาก Inkscape)

ในการพิมพ์แต่ละตัว จะแยกโฟลเดอร์ไปเป็นรายปีและรายเดือนตามลำดับ โดยตั้งชื่อเป็นวันที่วันที่พิมพ์

รายละเอียดดังนี้

ส่วนของ samba
$ sudo vi /etc/samba/smb.conf

...
[FaxOut]
    path = /samba/data/smbprn/tif
    create mask = 0777
    printing = bsd
    printable= yes
    Print command = "/usr/local/bin/d.faxout %s"

[FaxIn]
    path = /samba/data/smbprn/tif
    create mask = 0777
    printing = bsd
    printable= yes
    Print command = "/usr/local/bin/d.faxin %s"

[PrintToPDF]
    path = /samba/data/smbprn/tif
    create mask = 0777
    printing = bsd
    printable= yes
    Print command = "/usr/local/bin/d.printtopdf %s"

...

$ sudo /etc/init.d/samba restart

ส่วนของสคริปต์
$ cd /usr/local/bin
$ sudo vi d.faxout

#!/bin/bash
ROOT="/samba/data"
FAXROOT="$ROOT/FaxOut"
LOG="$ROOT/smbprn/tif"
DATE=`date +%F`
MONTH=`date +%m`
let "YEAR=`date +%G` + 543"
TARGET="$FAXROOT/$YEAR/$MONTH"
mkdir -p $TARGET
chmod 777 $TARGET
gs -dBATCH -sDEVICE=tiffg3 -sOutputFile="$TARGET/$DATE-%s.tif" %s > $LOG/smb-FaxOut.log
rm %s

$ sudo vi d.faxin

#!/bin/bash
ROOT="/samba/data"
FAXROOT="$ROOT/FaxIn"
LOG="$ROOT/smbprn/tif"
DATE=`date +%F`
MONTH=`date +%m`
let "YEAR=`date +%G` + 543"
TARGET="$FAXROOT/$YEAR/$MONTH"
mkdir -p $TARGET
chmod 777 $TARGET
gs -dBATCH -sDEVICE=tiffg3 -sOutputFile="$TARGET/$DATE-%s.tif" %s > $LOG/smb-FaxIn.log
rm %s

$ sudo vi d.printtopdf

#!/bin/bash
ROOT="/samba/data"
FAXROOT="$ROOT/PrintToPDF"
LOG="$ROOT/smbprn/tif"
DATE=`date +%F`
MONTH=`date +%m`
let "YEAR=`date +%G` + 543"
TARGET="$FAXROOT/$YEAR/$MONTH"
mkdir -p $TARGET
chmod 777 $TARGET
gs -dBATCH -sDEVICE=pdfwrite -sOutputFile="$TARGET/$DATE-%s.pdf" %s > $LOG/smb-PrintToPDF.log
rm %s

$ sudo chmod 755 d.faxout d.faxin d.printtopdf

ส่วนของการแมปเครื่องพิมพ์
$ sudo lpadmin -p FaxOut -u allow:all -E -v smb://$USER:$PASSWORD@server/FaxOut
$ sudo lpadmin -p FaxIn -u allow:all -E -v smb://$USER:$PASSWORD@server/FaxIn
$ sudo lpadmin -p PrintToPDF -u allow:all -E -v smb://$USER:$PASSWORD@server/PrintToPDF

เสร็จแล้ว

(ลองกับเซิร์ฟเวอร์ lenny ลูกข่าย sid)

samba: 3.0.27a กับ Win98

ช่วงนี้ใครอัปเกรด samba บน lenny หรือ sid ถ้ายังมีลูกข่ายเป็น Win9X ต้องเพิ่มพารามิเตอร์ ในส่วน [global]

...
   lanman auth = yes
...

แล้วก็อย่าลืมเริ่ม samba ใหม่ด้วย
$ sudo /etc/init.d/samba restart
ไม่งั้นล๊อกอินไม่เข้า

ถ้าแก้แล้วยังล๊อกไม่เข้าอีก อาจต้องเพิ่มผู้ใช้ของ samba ใหม่ (เพราะข้อมูลเดิมอาจถูกเขียนทับไปแล้ว)
$ sudo smbpasswd -a USER

อ้างอิง
Debian Bug report logs - #456977
samba: Windows 98/Me client with an existing user (good password) ask for a password to access IPC$

Topic: 

samba: symlinks

samba รุ่นตั้งแต่ 3.5 เป็นต้นมา ไม่อนุญาตให้ใช้ symlinks ในการโยงไดเรคทอรี่ไปที่อื่น
สามารถแก้ไขได้ 2 วิธี คือ

  • แก้ smb.conf ดังนี้
    ...
    [global]
        unix extensions = no
    
    ...
    [share2]
        ...
        wide links = yes
        follow symlinks = yes    #default
    ...

    วิธีนี้มีข้อเสียคือ permission ของผู้ใช้และกลุ่ม จะเพี้ยน อาจมีปัญหาในการเขียนไฟล์

  • ใช้การ mount แบบ bind แทนการใช้ symbolic links
    เช่นเดิมเคยโยงว่า
    # ln -sf /samba/share1/dir1 /samba/share2/dir1

    ให้เปลี่ยนเป็น

    # mkdir /samba/share2/dir1
    # mount -o bind /samba/share1/dir1 /samba/share2/dir1

    เป็นต้น

    เราสามารถทำให้เป็นอัตโนมัติได้ด้วยการนำไปใส่ไว้ใน smb.conf ดังนี้

    ...
    [share2]
        ...
        root preexec = sh -c "mount -o bind /samba/share1/dir1 /samba/share2/dir1"
    ...
    

จบแล้ว

Topic: 

samba: บันทึกเกร็ดการเมานต์

update 50-10-20
ตอนที่ทดลองนี้ cifs บนเดเบียน sid (samba-3.0.26a-1) แก้ปัญหาเรื่องแคชไม่ตรง และล๊อกเรคคอร์ดช้าได้แล้ว
โดยการแก้ไขไฟล์ smb.ini ในหมวด share ให้มีพารามิเตอร์คือ

[data]
    ...
    strict locking = yes
    oplocks = yes
    level2 oplocks = no
    ...

และเมานต์ด้วยพารามิเตอร์ directio เช่น
$ sudo mount -t cifs //server1/data /mnt/smbdata -o username=USER,password=PASSWORD,iocharset=utf8,directio

จะสามารถล๊อกเรคคอร์ดได้ตรงและแก้ปัญหาแคชไฟล์ได้แล้วครับ
*****

ข้อความเดิม
เที่ยวนี้ ถือเป็นการบันทึกกันลืม เพราะยังไม่มีความแน่ใจในการทดสอบ

สำหรับเครื่องลูกข่ายที่เป็นวินโดวส์ ใช้งานได้ดีไม่มีปัญหา
แต่สำหรับเครื่องลูกข่ายที่เป็นลินุกซ์ ได้เคยทดสอบมานานแล้วเกี่ยวกับการเมานต์ samba แบบต่าง ๆ
ช่วงนี้ได้มีโอกาสมาทดสอบดูอีกครั้งนึง พบว่า...

  • การเมานต์แบบใช้ smbfs ไม่สามารถล๊อกไฟล์และเรคคอร์ดได้ (จริง ๆ ล๊อกได้แต่เฉพาะเครื่องตัวเอง) แต่การทำงานรวดเร็วและถูกต้องดี
  • การเมานต์แบบ cifs สามารถล๊อกไฟล์และเรคคอร์ดข้ามเครื่องได้ แต่การทำงานช้ามาก และมีปัญหากับการแคชการอ่าน ทำให้บ่อยครั้งอ่านข้อมูลได้ไม่ตรง

ดูแนวโน้มแล้ว อนาคตคงจะไปลงที่ cifs ทั้งหมด แต่สำหรับตอนนี้ ถ้าต้องมีการล๊อกเรคคอร์ดข้ามแพลตฟอร์มระหว่างวินโดวส์กับลินุกส์ คงต้องเลือกใช้ smbfs โดยเขียนรูทีนการล๊อกไฟล์และเรคคอร์ดขึ้นมาใช้เอง น่าจะเป็นทางออกที่ดีที่สุด

บันทึกลิงก์ชั้นดีของ samba อีกนิด

samba: MSDN

ติดตั้ง Visual Foxpro เสร็จแล้ว เกิดปัญหาว่า MSDN คือ ความช่วยเหลือใช้งานไม่ได้

แก้ปํญหาด้วยการใช้ Network Drive Letter แทน Network Reference
เช่นสมมุติว่าเราแม็ปไดร์ฟ G: จาก \\server\app
เวลาเขาขึ้นมาถามหาไฟล์ ให้เราเปลี่ยนจาก \\server\app เป็น g:\ แทน
ก็จะสามารถใช้งานได้

Topic: 

samba: บันทึกเรื่องไอพี

ปกติใช้งาน samba โดยใช้เครื่องลูกข่ายที่เป็นแบบไอพีคงที่ตลอด
เนื่องจากมักมีเครื่องพิมพ์หรืออุปกรณ์อื่นที่ติดกับเครื่องลูกข่ายนั้น ๆ
เมื่อเราต้องการใช้งานเครื่องพิมพ์ การอ้างถึงไอพีตรง ๆ หรืออ้างชื่อโดยผ่าน dns ภายใน จะทำได้สะดวกกว่า

วันนี้ซ่อมเครื่องลูกข่ายไปเครื่องนึง ลืมกำหนดไอพีแอดเดรส ไอพีของเครื่องที่ซ่อมจึงถูกกำหนดโดย dhcp server
ผลคือทำให้ samba ป่วนไปหมด ในทุกเครื่องลูกข่ายที่เป็นวินโดวส์
ค้นไปค้นมาจึงพบว่าลืมตั้งไอพีสำหรับเครื่องที่ทำการซ๋อม พอกำหนดไอพีเสร็จ ปัญหาก็เรียบร้อย

เข้าใจว่า samba คงเก็บค่าไอพีในการล๊อกไฟล์และเรคคอร์ดเป็นหลัก ดังนั้นเมื่อไอพีเปลียนไป ทำให้ samba รับภาระโหลดมากเกินไป จึงทำให้ป่วนดังกล่าว

จึงบันทึกไว้เตือนความจำว่า สำหรับ samba แล้ว ถ้ามีการใช้งานผสมกันระหว่าง ลินุกส์และวินโดวส์ ควรกำหนดไอพีให้เครื่องลูกข่ายเป็นแบบคงที่เท่านั้น

Topic: 

samba: ลองเขียน foxpro ทำการล๊อกไฟล์และเรคคอร์ดใช้เอง

update 50-10-20
ตอนที่ทดลองนี้ cifs บนเดเบียน sid (samba-3.0.26a-1) แก้ปัญหาเรื่องแคชไม่ตรง และล๊อกเรคคอร์ดช้าได้แล้ว
โดยการแก้ไขไฟล์ smb.ini ในหมวด share ให้มีพารามิเตอร์คือ

[data]
    ...
    strict locking = yes
oplocks = yes
level2 oplocks = no
    ...

และเมานต์ด้วยพารามิเตอร์ directio เช่น
$ sudo mount -t cifs //server1/data /mnt/data -o username=USER,password=PASSWORD,iocharset=utf8,directio

จะสามารถล๊อกเรคคอร์ดได้ตรงและแก้ปัญหาแคชไฟล์ได้แล้วครับ

เป็นแค่การทดลองเท่านั้น

ถ้าเครื่องลูกข่ายของ foxpro เป็นวินโดวส์ล้วน ไม่ต้องใช้ฟังก์ชั่นในบล๊อกอันนี้ ซึ่งเป็นการเขียนฟังก์ชั่นเพื่อแก้ปัญหาการล๊อกเรคคอร์ดสำหรับลูกข่ายที่เป็นลินุกซ์เท่านั้น

เนื่องจากการเมานต์แบบ cifs มีปัญหากับแคช ทำให้การอ่านค่าเรคคอร์ดในไฟล์ไม่ตรง จึงต้องเลือกใช้การเมานต์แบบ smbfs แทน ซึ่งการเมานต์แบบ smbfs มีข้อเสียอย่างแรงคือ ไม่สามารถล๊อกไฟล์และเรคคอร์ดได้ จึงทดลองเขียนฟังก์ชั่นการล๊อกไฟล์ขึ้นมาใช้เอง
(ยังค้นคำตอบสำหรับการนี้ในกูเกิลไม่พบ - พบแต่คำถาม ไม่พบคำตอบ ส่วนใหญ่ย้ายไปใช้ระบบฐานข้อมูลกันหมด)

วิธีการคือสร้างไฟล์ข้อมูล dbf ขึ้นมาเก็บค่า ตาราง, เลขที่เรคคอร์ด, เครื่องที่ทำการล๊อก, และเวลาตอนล๊อก
เวลาต้องการล๊อกไฟล์และเรคคอร์ด ก็ให้มาเขียนลงในไฟล์นี้ทุกครั้ง และตอนปลดล๊อกก็ลบออกทุกครั้งเช่นกัน
โดยเวลาเรียกใช้สำหรับการล๊อกไฟล์ ก็เรียกด้วยฟังก์ชั่น =fxflock() และการล๊อกเรคคอร์ดก็เรียกด้วยฟังก์ชั่น =fxrlock()

จากการทดลองพบว่า ถึงแม้แคชของ smbfs จะเร็วกว่า cifs มากก็ตาม แต่ก็ยังไม่ใช่แบบทันทีทันใด
เราจะแก้ปัญหาแคชด้วยการใช้คำสั่ง foxpro ว่า go recno() เพื่ออัปเดตแคช

และพบว่าถ้าเรามีการ เปลี่ยนแปลงข้อมูลในเรคคอร์ด จะทำให้การอัปเดตรวดเร็วขึ้น จึงใช้เทคนิกอันนี้ในการรีเฟรช โดยทุกครั้งที่เกิดการรีเฟรช จะเขียนชื่อเครื่อง (gcMachineName) ลงไปที่เรคคอร์ดแรกของไฟล์ lockhndl

ถึงแม้จะแก้ปัญหาได้ดีพอควรก็ตาม แต่ยังไม่พอสำหรับการล๊อกไฟล์ ซึ่งเราต้องปล่อยให้เร็วที่สุด
ดังนั้นสำหรับการล๊อกไฟล์ จะกันเหนียวอีกชั้นนึงด้วยการเขียนลงไฟล์สำหรับการล๊อค (ข้อมูลว่าง ๆ ) มาช่วยอีกแรงนึง จึงสามารถล๊อกและปล่อยล๊อกได้แบบทันทีทันใด

เนื่องจากมีการใช้ข้อมูลในการล๊อกเป็นชื่อเครื่องด้วย ซึ่งปรกติเราเรียกผ่านฟังก์ชั่น foxpro คือ sys(0) แต่พบว่าเครื่องลูกข่ายที่เป็นลินุกซ์ (+dosemu+freedos) ไม่มีข้อมูลตัวนี้ เราจึงต้องกำหนดข้อมูลตัวนี้ขึ้นมาเองในทุก ๆ เครื่อง ซึ่งในโค๊ดจะปรากฎในชื่อตัวแปร gcMachineName

ส่วนโค๊ด

function fJustFName && RETURN JUST FILENAME
parameter cFile
    private cLoc,cSep
    cLoc=locfile(cFile)
    cSep=iif('/'$cLoc,'/','\')
return right(cLoc,len(cLoc)-rat(cSep,cLoc))

function fJustPath  && RETURN JUST FILENAME
parameter cFile,lIsIncludeSep
    private cLoc,cSep
    cLoc=locfile(cFile)
    cSep=iif('/'$cLoc,'/','\')
    if lIsIncludeSep
        return left(cLoc,rat(cSep,cLoc))
    else
        return left(cLoc,rat(cSep,cLoc)-1)
    endif
return

function fJustStem  && RETURN STEM OF FILENAME
parameter cFile
    private cName
    cName=fJustFName(cFile)
return left(cName,rat('.',cName)-1)

function fxflock    && RETURN FLOCK STATUS
*   SOLVED LOCKED FAIL IN LINUX
*   BY CREATE NEW LOCKED TABLE TO HANDLE LOCKED STATE
*       FLOCK([<expN> | <expC>])
parameter xArea
return fxSubLock(xArea, 0)

function fxrlock    && RETURN RLOCK STATUS
*   SOLVED LOCKED FAIL IN LINUX
*   BY CREATE NEW LOCKED TABLE TO HANDLE LOCKED STATE
*       RLOCK([<expN> | <expC1>]
parameter xArea
return fxSubLock(xArea, -1)

function fxFlushLock
parameter cFile
    use (cFile)
    go 1    && RESERVE FIRST RECORD FOR FLUSH DATA
    replace ftable with gcMachineName
    go bott
    flush
    go 1
    list nocon
    use
    flush
return

function fxSubLock
parameter xArea, nRecno
    private cTable,nLoop
    nLoop=50        && TRY TO LOCK FOR 50 TIMES
    cLockHndl='lockhndl'
    =fxCrLockHndl()
    nOldArea=sele()
    xTemp=type('xArea')
    if xTemp='N' .or. xTemp='C'
        sele (xArea)
    else
        if len(dbf())=0
            return .F.
        endif
    endif
    if nRecno=-1
        nRecno=recno()
    endif
    cTable=fjuststem(dbf())
    *****
    if nRecno=0
        do while file(cTable+'.LCK') .and. nLoop>0
            wait wind "Wait file lock "+cTable timeout .1
        enddo
        if nLoop=0
            return .F.
        endif
        nloop = 50
    endif
    if nRecno=0
        cSafe = set('safe')
        set safe off
        disp to file (cTable+'.LCK') noconsole
        set safe &cSafe
    endif
    *****
    sele 0
    =fxFlushLock(cLockHndl)
    use (cLockHndl)
    locate for fTable=cTable .and. (fRecno=nRecno .or. fRecno=0) .and. fMachine!=gcMachinename
    do while found() .and. nLoop > 0
        *wait wind "Wait for unlock..." timeout 1
        wait wind str(nloop,3)+" wait "+ftable+str(frecno,4) timeout .1
        *wait wind "Wait for unlock..." nowait
        go recno()
        go bott
        go top
        locate for fTable=cTable .and. (fRecno=nRecno .or. fRecno=0) .and. fMachine!=gcMachinename
        nLoop=nLoop-1
    enddo
    if nLoop<=0
        wait wind "Lock failed" nowait
        use
        =fxFlushLock(cLockHndl)
        sele (nOldArea)
        return .F.
    endif
    wait wind "pl" nowait   && PASS LOCK
    locate for fTable=cTable .and. fMachine=gcMachineName
    if ! found()
        locate for fTable=" "
        if ! found()
            appe blank
        endif
        repl fTable with cTable, fMachine with gcMachineName
    endif
    repl fRecno with nRecno, fSeconds with int(seconds())
    *CLEAR UNFINISH WORK
    =fxClearLongLock()
    use
    =fxFlushLock(cLockHndl)
    sele (nOldArea)
return .T.

function fxClearLongLock
    nSeconds=seconds()
    repl fTable with " ", fMachine with " ";
        fRecno with 0, fSeconds with 0;
    for fMachine=gcMachineName .and. abs(fSeconds-nSeconds)>120;
        .and. fSeconds!=0
return .T.

function fxCrLockHndl
    cLockHndl='lockhndl'
    if ! file(cLockHndl+'.dbf')
        create table (cLockHndl) (;
            fTable  c (20);
            ,fRecno n (10);
            ,fMachine   c (20);
            ,fSeconds   n (10)  )
    endif
return .T.

function fxUnlock
*   SOLVED LOCKED FAIL IN LINUX
*   BY CREATE NEW LOCKED TABLE TO HANDLE LOCKED STATE
*       UNLOCK [IN <expN> | <expC> | '*ALL']
parameter xArea
    cLockHndl='lockhndl'
    =fxCrLockHndl()
    nOldArea=sele()
    xTemp=type('xArea')
    if xTemp='C' .and. upper(xArea)='*ALL'
        sele 0
        =fxFlushLock(cLockHndl)
        use lockhndl
        repl fTable with ' ', fRecno with 0;
            , fMachine with ' ', fSeconds with 0;
            for fMachine=gcMachineName
        *CLEAR UNFINISH WORK
        =fxClearLongLock()
        use
        =fxFlushLock(cLockHndl)
        sele (nOldArea)
        return .T.
    endif
    if xTemp='N' .or. xTemp='C'
        sele (xArea)
    else
        if len(dbf())=0
            return .F.
        endif
    endif
    cTable=fjuststem(dbf())
    if file(cTable+'.LCK')
        dele file (cTable+'.LCK')
    endif
    sele 0
    =fxFlushLock(cLockHndl)
    use (cLockHndl)
    repl fTable with ' ', fRecno with 0;
        , fMachine with ' ', fSeconds with 0;
        for fMachine=gcMachineName .and. fTable=cTable
    *CLEAR UNFINISH WORK
    =fxClearLongLock()
    use
    =fxFlushLock(cLockHndl)
    sele (nOldArea)
return .T.

เรียกใช้งานด้วย

=fxflock() && IN CURRENT AREA
...DO UPDATE...
=fxunlock()

และ

=fxrlock() && IN CURRENT AREA AND CURRENT RECORD
...DO UPDATE...
=fxunlock()

ลองใช้งานแล้วได้ผลดีพอควร แต่ยังขาดความสมบูรณ์อีกมาก ถ้าจะนำไปใช้จริงควรปรับแก้เอาเองครับ

Topic: 

ย้ายจาก samba ไป nfs สำหรับ dosemu (ro)

การใช้งาน samba กับ dosemu พบว่าตั้งแต่ samba รุ่น 3.0.27 เป็นต้นมา สำหรับแชร์ที่เป็นแบบอ่านเขียน พบว่ามีการล๊อกเรคคอร์ดที่ดีขึ้น ด้วยพารามิเตอร์ directio
แต่สำหรับแชร์ที่เป็นแบบอ่านอย่างเดียว พบว่ามีปัญหามาก เพราะถึงแม้ว่าเราจะกำหนดให้เป็นแบบอ่านอย่างเดียว แต่เขาไม่ยอมให้เปิดไฟล์ซ้ำ
อย่ากระนั้นเลย เนื่องจากเป็นแบบอ่านอย่างเดียว เราไม่จำเป็นต้องทำเรื่องล๊อกเรคคอร์ด ขอย้ายมาใช้ nfs เลยดีกว่า

ที่เซิร์ฟเวอร์

ติดตั้ง
# aptitude install nfs-common nfs-kernel-server

ทำการแชร์ สมมุติว่าจะแชร์ไดเรกทอรี่ชื่อ /samba/app ให้เป็นแบบอ่านอย่างเดียว โดยให้ทุกเครื่องในวงภายในคือ 192.168.*.* สามารถใช้งานได้
# vi /etc/exports

# /etc/exports: the access control list for filesystems which may be exported
#       to NFS clients.  See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes       hostname1(rw,sync) hostname2(ro,sync)
#
# Example for NFSv4:
# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt)
# /srv/nfs4/homes  gss/krb5i(rw,sync)
#
/samba/app   192.168.0.0/16(ro)

เริ่ม nfs ใหม่
# /etc/init.d/nfs-kernel-server restart

เสร็จแล้ว

ที่เครื่องลูกข่าย

ติดตั้ง
$ sudo aptitude install nfs-client

เมานต์ สมมุติว่าเซิร์ฟเวอร์ชื่อ server1 และจะเมานต์ไปที่ /mnt/app
$ sudo mount -t nfs server1:/samba/app /mnt/app

ใช้งานได้แล้ว

อ้างอิง

เรียกใช้งานจาก dos ดิสเก็ต 1 แผ่น

จากกระทู้ มีใครอยากใช้ Linux Server แทน Netware Server บ้างครับ ? อันแสนฮิต เลยอยากลองศึกษา

ได้ความดังนี้ครับ

จากบทความของคุณ ninetea เธอเอาสามเรื่องมารวมกัน คือเรื่อง ltsp, เรื่อง samba และเรื่องการดัดแปลง ltsp มาใช้กับ FreeDos
ตอนศึกษาเลยทำให้งง
แต่ผมจะพยายามแยกเป็นส่วน ๆ เผื่อเอาไว้ให้สามารถปรับเปลี่ยนได้หลาย ๆ แบบ

เรื่องที่จะเขียนวันนี้ก็คือเรื่องของการเรียกเข้าหา samba จาก FreeDos โดยใช้ดิสเก็ตแผ่นเดียว

เริ่มด้วยไปดาวน์โหลดแผ่นดิสเกตที่ทำหน้าที่เป็นไคลเอนต์ของ samba
ที่ Bart's Network Boot Disk
โฮมเพจอยู่ที่ http://www.veder.com/nwdsk

ไฟล์นี้ใหญ่ประมาณ 1.6MB ถ้าใครมีเครื่องดิสเก็ตไดรฟว์ขนาด 2.88MB ก็สามารถเขียนลงแผ่นและเรียกใช้งานได้เลย ด้วยคำสั่ง
$ dd if=fdmsrrc.img of=/dev/fd0

แต่ถ้าหากมีเพียงเครื่องอ่านขนาด 1.44MB เราต้องเอามาตัดไดรฟ์เวอร์ทิ้งบางตัว (คือตัวที่ไม่ใช่ฮาร์ดแวร์ของเรา) เพื่อทำให้แผ่นดิสเก็ตมีขนาดไม่เกิน 1.44MB
ไดร์ฟเวอร์อยู่ภายใต้ไดเรคทอรี่ /LIB/NDIS ครับ

เริ่มด้วย
็คัดลอกทำสำเนาในชื่อ fdms160.img
$ cp fdmsrrc.img fdms160.img

เอาเครื่องมือมาก่อน คือ mtools
$ sudo apt-get install mtools

จะทำให้ fdms160.img เป็นไดร์ฟ x:
และ fdms144.img เป็นไดร์ฟ y:
โดยการแก้ไข ~/.mtoolsrc
$ vi ~/.mtoolsrc

drive x: file="~/fdms160.img"
drive y: file="~/fdms144.img"

เอาบูตเรคคอร์ดจาก fdms160.img มาเตรียมไว้ก่อน
$ dd if=fdms160.img of=bootblock bs=512 count=1

สร้างอิมเมจอันใหม่ให้มีขนาด 1.44MB ชื่อ fdms144.img โดยเอาบูตเรคคอร์ดที่สร้างเตรียมไว้ เขียนลงไปด้วย
$ mformat -C -f 1440 -B bootblock y:

คัดลอกไฟล์สำคัญตามลำดับ คือ kernel.sys และ command.com
$ mcopy x:/KERNEL.SYS y:
$ mcopy x:/command.com y:

ที่เหลือจะเป็นการทยอยลบไฟล์ไดร์ฟเวอร์ใน fdms160
ผมเลือกใช้ mc (Midnight Commander) ยอดฮิต
$ sudo apt-get install mc

เมานต์ fdms160 ไว้ใน /tmp/fdms160
$ mkdir -p /tmp/fdms160
$ sudo mount -o loop fdms160.img /tmp/fdms160

และเมานต์ fdms144 ไว้ใน /tmp/fdms144
$ mkdir -p /tmp/fdms144
$ sudo mount -o loop fdms144.img /tmp/fdms144

ลบไฟล์
$ sudo mc
# cd /tmp/fdms160/

ไฟล์ที่ลบ สามารถดูเทียบได้กับการ์ดแลนที่เรามีกับโฮมเพจของ NwDsk ภายใต้หัวข้อ List of ODI 16-bit Nic drivers

ลบไฟล์ไปสักครึ่งนึงก็ใช้ได้ครับ
เมื่อลบเสร็จแล้วก็คัดลอกไฟล์ด้วย mc ต่อได้เลย
ใช้ [TAB] ในการเปลี่ยนข้าง และ F5 ในการคัดลอกไฟล์
เมื่อเสร็จเรียบร้อยแล้วก็ออกจาก mc ด้วย F10 หรือ F9+Exit

ยกเลิกการเมานต์ก่อน
$ sudo umount /tmp/fdms160
$ sudo umount /tmp/fdms144

เขียนลงแผ่น
$ dd if=fdms144.img of=/dev/fd0

เรียบร้อยแล้่ว สามารถบูตเพื่อติดตั้งได้เลย
ตอนติดตั้ง อย่าลืมบันทึกค่าเอาไว้ เพื่อเก็บไว้ใช้ในการบูตครั้งต่อไป

หากต้องการพัฒนาต่อเป็น ltsp ก็สามารถบันทึกดิสเก็ตแ่ผ่นนี้ไว้ใช้สำหรับบูตในเซิร์ฟเวอร์ได้
โดยใช้คำสั่ง
$ dd if=/dev/fd0 of=freedos.img
$ mcopy a:/KERNEL.SYS .
$ mknbi-fdos --output=freedos.nb KERNEL.SYS freedos.img

แล้วนำเอาไฟล์ freedos.nb ที่ได้ ไปใส่ในไดเรคทอรี่ของ /tftpboot ในเครื่องเซิร์ฟเวอร์ บวกปรับแต่ง dhcp นิดหน่อย ก็ใช้ได้ครับ

ข้อเสียของการใช้ดิสก์แผ่นเดียวคือ ต้องใช้แผ่นดิสเกตในการบูตทั้งระบบ ทำให้เริ่มต้นระบบช้า
ข้อดีคือวิธีการไม่ยุ่งยากเหมือน ltsp

ตัวอย่างการประยุกต์ใช้งาน

หมวด global
ทำให้แชร์ข้ามวงได้

    hosts allow = 192.168.0.0/16

ทำเป็นปรินเตอร์เซิร์ฟเวอร์ผ่าน cups

    load printers = yes
    printing = cups
    printcap name = cups
    printer admin = @smbgroup

หมวด share
เร่งความเร็ว (ใช้กับแชร์ที่อ่านได้อย่างเดียว)

    fake oplocks = yes

ต้องการอ่านจาก system backup ซึ่งปกติไม่ได้เมานต์ไว้
ดังนั้นก่อนใช้งานก็ต้องสั่งให้เมานต์ก่อน

[sysbak]
    comment = System Backup Dir
    path = /sysbak
    valid users = @smbgroup
    root preexec = mount /sysbak

เครื่องพิมพ์เทียมเก็บไฟล์ pdf

[printtopdf]
    path = /samba/data/smbprn/pdf
    create mask = 0777
    printing = bsd
    printable= yes
    Print command = DATE=`date +%F`;LOG="/samba/data/smbprn/pdf";gs -dBATCH -
sDEVICE=pdfwrite -sOutputFile=/samba/data/smbprn/$DATE-%s.pdf %s > $LOG/smb-pdf.l
og;rm %s
    valid users = @smbgroup
    public = yes

เครื่องพิมพ์เทียมเก็บแฟกซ์เป็น tiff

[printtotiff]
    path = /samba/data/smbprn/tif
    create mask = 0777
    printing = bsd
    printable= yes
    Print command = DATE=`date +%F`;LOG="/samba/data/smbprn/tif";gs -dBATCH -
sDEVICE=tiffg3 -sOutputFile=/samba/data/fax/FaxOut/$DATE-%s.tif %s >
$LOG/smb-FaxOut.log;rm %s
    valid users = @smbgroup
    public = yes

เป็นเครื่องแฟกซ์ โดยทำงานประสานกับ HylaFax-Server
(ต้องติดตั้ง hylafax-server ด้วย)

[hylafax]
    path = /tmp
    create mask = 0777
    printable = yes
    printcap name = lpstat
    printing = cups
    use client driver = Yes
    print command = lp -d%p -oraw %s; rm %s
    lpq command = lpstat -o%p
    lprm command = cancel %p-%j
    queuepause command = disable %p
    queueresume command = enable %p
    printer admin = @smbgroup
Topic: