การ Restart Service โดยอัตโนมัติ

มีศิษย์เก่าส่งคำถามเข้ามาหาผู้เขียนเกี่ยวกับการ Restart Service ของ Reporting Service โดยให้เกิดขึ้นอัตโนมัติในทุก ๆ เช้า ซึ่งผู้เขียนยังไม่ทราบความจำเป็นถึงเหตุผลที่ชัดเจน อย่างไรก็ตาม การ Restart Service ของ Reporting Service
การ Restart Service โดยอัตโนมัติ
ทักษะ (ระบุได้หลายทักษะ)

การ Restart Service โดยอัตโนมัติ

มีศิษย์เก่าส่งคำถามเข้ามาหาผู้เขียนเกี่ยวกับการ Restart Service ของ Reporting Service โดยให้เกิดขึ้นอัตโนมัติในทุก ๆ เช้า
ซึ่งผู้เขียนยังไม่ทราบความจำเป็นถึงเหตุผลที่ชัดเจน

อย่างไรก็ตาม การ Restart Service ของ Reporting Service สามารถทำได้ 2 วิธี คือ
1.สามารถสั่งผ่าน Jobs บน SQL Server Agent Service  
2.สามารถสั่งผ่าน Schedule Task ของ Microsoft Windows  

ทั้งนี้ ผู้เขียนจึงจะแสดงให้ดูทั้ง 2 แบบเลย

ผู้อ่านต้องเข้าใจก่อนว่าการ Start, Stop หรือ Restart Service นั้นจะต้องทำผ่าน Users
ที่อยู่ในกลุ่ม Local Administrators ของ Microsoft Windows เครื่องที่ติดตั้ง Service ดังกล่าวอยู่
(อันที่จริงแล้วสามารถ Delegate ให้ user เป็นราย User สามารถ Start หรือ Stop Service เป็นราย Service ได้เป็นการเฉพาะแต่ไม่ขอกล่าวในบทความนี้)
สามารถดูได้ผ่านทาง Computer Management Console ภายใต้ Local Users and Groups ดังแสดง

Local Users and Groups

จากนั้นดับเบิ้ลคลิกเข้าไปที่ Local Administrators
 
จะพบว่ามี User โดย Default อยู่ 2 คนก็คือ Local Administrator ของเครื่องนั้น ๆ
และ กรุ๊ป Domain Admins จาก Domain นั้นเอง

Local Administrators

ในกรณีนี้ผู้เขียนจะสร้าง User แยกต่างหากจาก User ที่มีอยู่แล้ว

เพื่อแสดงให้เห็นว่าผู้อ่านสามารถนำเอา Local user หรือ Domain user มาใช้ได้ดังแสดง

Local use

กรณีนี้ผู้เขียนเลือกสร้าง Local User ชื่อ Restarter ลงในเครื่องนั้น ๆ

จากนั้นทำการเพิ่ม Restarter ลงในกลุ่ม Local Administrators ดังแสดง

Local User

เพียงแค่นี้เราก็จะได้ User ที่มีสิทธิ์ในการ Start และ Stop Service เรียบร้อยแล้ว

แบบที่ 1 สร้างเป็น Jobs บน SQL Server Agent Service

ผู้อ่านต้องเข้าใจเงื่อนไขเกี่ยวกับคนที่เรียกใช้ Job Steps อย่างถูกต้องเสียก่อนดัง Diagram ต่อไปนี้

สร้างเป็น Jobs บน SQL Server Agent Service

กรณี Job Step เป็น Transact SQL Script จะรันโดย Job Owner เอง
หากว่า Job Owner นั้นไม่ครองบทบาทของ Sysadmin บนฝั่ง Database Engine
แต่ หาก Job Owner นั้นครองบทบาทของ Sysadmin บนฝั่ง Database Engine แล้วละก็จะรันภายใต้ Service Account ของฝั่ง SQL Server Agent Service

กรณี Job Step ไม่ใช่ Transact SQL Script จะรันโดย Service Account ของฝั่ง SQL Server Agent Service หรือ สามารถกำหนดให้รันภายใต้ Proxy Account ได้

ในครั้งนี้จะเลือกประเภท Job Step เป็น Operating System ซึ่งไม่ใช่ Transact SQL Script

ดังนั้น จึงมีทางเลือกคือรันภายใต้ Service Account ของฝั่ง SQL Server Agent Service
หรือไม่ก็รันภายใต้ Proxy Account หากต้องการให้ Service Account ของฝั่ง SQL Server Agent Service
สามารถ Start หรือ Stop Service ได้นั้นจำเป็นต้องนำเอา Service Account ดังกล่าวใส่ลงในกลุ่ม Local Administrators ซึ่งไม่ควรทำ เพราะไม่สอดคล้องกับ Security Best Practice

(สำหรับเรื่องนี้แนะนำให้เข้าอบรมหลักสูตร Microsoft SQL Server Database Administrator ของสถาบัน 9Expert)

ดังนั้นจึงเหลือทางเลือกเดียวคือสร้างและใช้งาน Proxy Account

ก่อนที่จะใช้งาน Proxy Account นั้นจำเป็นจะต้องสร้าง Credential ไว้ที่ฝั่ง Database Engine เสียก่อน ดังแสดง
 

Proxy Account

Credentials เป็น Object เกี่ยวกับ Security ในระดับ Instance หรือระดับ Server ดังรูป

Credentials เป็น Object เกี่ยวกับ Security

Credential เป็นการนำเอา Username และ Password ของผู้ใช้ใน Windows มาจัดเก็บไว้ในฐานข้อมูล
เมื่อต้องการเข้าถึงทรัพยากรตามสิทธิของผู้ใช้คนนั้น ๆ  ก็สามารถนำเอา Credential ไปเข้าถึงทรัพยากรได้
 
เราไม่จำเป็นต้องเพิ่ม Windows User เข้าเป็น Login ใน SQL Server แต่อย่างใด

เมื่อผู้เขียนเพิ่ม Credential ลงในฝั่ง Database Engine เรียบร้อยแล้ว จะกลับไปที่ฝั่ง SQL Server Agent Service เพื่อสร้าง Proxy 

เปิดโฟลเดอร์ Proxies ภายใต้ SQL Server Agent Service จะพบโฟลเดอร์ของบรรดาชนิด Job Step
ให้คลิกขวาไปที่โฟลเดอร์ Proxies จากนั้นเลือก New Proxy  
Proxies จากนั้นเลือก New Proxy

จะปรากฏหน้าต่างดังแสดง ให้กำหนด

  • ชื่อ Proxy
  • อ้างถึง Credential ที่สร้างไว้บน Database Engine

จากนั้นระบุว่า Proxy สามารถใช้ได้ใน Job Step ชนิดใดบ้าง

Proxy สามารถใช้ได้ใน Job Step ชนิดใดบ้าง

จะได้ผลลัพธ์ดังแสดง หมายความว่าหาก Job Step มีเลือกรันผ่าน Proxy ชื่อ Proxy-Restarter
ก็จะไปหยิบ Credential ชื่อ Credential-Restarter มาใช้นั่นเอง

Credential-Restarter

จากนั้นผู้เขียนจะตรวจสอบว่า Reporting Service เปิดใช้งานอยู่หรือไม่ ผ่านทาง SQL Server Configuration Manager ดังแสดง 

 SQL Server Configuration Manager

จากรูป หาก Reporting Service ไม่ได้อยู่ในสถานะ Running ให้ทำการ Start Service ขึ้นมา

ผู้อ่านโปรดสังเกตว่า Reporting Service ติดตั้งอยู่บน Named Instance ในที่นี้คือ SQL2
จากนั้นกลับไปที่ SQL Server Management Studio ในส่วนของ SQL Server Agent Service

ผู้เขียนทำสร้าง Job โดยการคลิกขวาไปที่โฟลเดอร์ Jobs และตั้งชื่อ Job เป็น STOP Reporting Service ดังแสดง

ตั้งชื่อ Job เป็น STOP Reporting Service

จากนั้นให้สร้าง Job Step ชนิด Operating System โดยใช้ Script แนะนำดังนี้

NET STOP ReportServer$SQL2 /y
NET STOP ReportServerWebApp$SQL2 /y
NET STOP SPTimerV4 /y
iisreset /stop

เนื่องจาก Reporting Service เป็น Named Instance จึงต้องอ้างชื่อ Service ในรูปแบบ ReportServer$<InstanceName>
และ Reporting Service มักใช้ร่วมกับ Microsoft Sharepoint Server และ IIS Server

ดังนั้นจึงเพิ่มเติมการ Stop Service ที่เกี่ยวข้องเหล่านี้ลงไปได้ ดังแสดง

Microsoft Sharepoint Server

ผู้อ่านโปรดสังเกตว่าต้องระบุ Run as: เป็น Proxy Account ที่เราสร้างขึ้นมา (ที่มีสิทธิในการ Start หรือ Stop Service)
จากนั้นทดลองรัน Job โดยการคลิกขวาไปที่ชื่อ Job แล้วเลือกไปที่ Start Job at Step ดังแสดง

using System;

namespace csharp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int a = Util.id;
            int b = Util.add(20, 30);
            Console.WriteLine("End.");
        }
    }
}

public static class Util
{
    public static int id = 123;

    public static int add(int a, int b)
    {
        return a + b;
    }
}

เมื่อกลับไปดูใน SQL Server Configuration Manager จะพบว่า Reporting Service มีสถานะเป็น Stopped ไปเรียบร้อยแล้ว ดังแสดง

 Reporting Service มีสถานะเป็น Stopped

เราสามารถติดตามดูประวัติการรันของ Job ได้ โดยคลิกขวาไปที่ชื่อของ  Job ของเรา
จากนั้นเลือกไปที่ View History จะแสดงหน้าต่างดังต่อไปนี้

using System;

namespace csharp1
{
    class Program
    {
        static void Main(string[] args)
        {
            bool isACar = true;
            int salary = 1;

            if (isACar)
                Console.WriteLine("abc");
            else
                Console.WriteLine("def");

            if (salary)
                Console.WriteLine("ghi");
            else
                Console.WriteLine("jkl");

            Console.WriteLine("End.");
        }
    }
}

จะพบว่า Job ถูกรันภายใต้ MIA-SQL\Restarter ที่เราสร้างไว้ และพบว่า SQL Server Reporting Service ได้ถูก Stop เป็นที่เรียบร้อย
แต่ หาก Stop เพียงอย่างเดียวก็อาจไม่ตรงกับที่มีผู้สอบถามเข้ามา ผู้เขียนเลยแก้ไขในส่วนของ Script เสียใหม่ให้เป็น

NET STOP ReportServer$SQL2 /y
NET STOP ReportServerWebApp$SQL2 /y
NET STOP SPTimerV4 /y
iisreset /stop

NET START ReportServer$SQL2
NET START ReportServerWebApp$SQL2
NET START SPTimerV4
iisreset /start

เพียงเท่านี้ก็จะกลายเป็นการ Restart Service ตามต้องการแล้ว

แบบที่ 2 กำหนดให้ Restart Service ผ่านทาง Task Scheduler

อีกวิธีหนึ่งที่ผู้เขียนเห็นว่าเหมาะสมมากกว่าวิธีแรก ก็คือการสร้างเป็น Task ภายใต้ Task Scheduler ของ Microsoft Windows ดังแสดง

กำหนดให้ Restart Service ผ่านทาง Task Scheduler

เมื่อเรียก Task Scheduler ขึ้นมาแล้ว ให้คลิกขวาไปที่ Task Scheduler Library เลือก Create Task จะปรากฏหน้าต่าง Create Task ดังแสดง

Task Scheduler Library เลือก Create Task

ในแท็บ General ทำการตั้งชื่อ Task ตามต้องการ
ตัวอย่างนี้ให้ชื่อว่า Restart Reporting Service

ในส่วนของ Security Options เป็นสิ่งสำคัญมาก จำเป็นต้องเลือก User หรือ Group ที่มีสิทธิ์เพียงพอในการ Restart Service
ในที่นี้ผู้เขียนการเลือกใช้ Local Administrators ซึ่งเป็น Group เป็นผู้รัน Task นี้เลย

จากนั้นเลือก Checkbox ชื่อ Run with highest Privileges (ในส่วนนี้ผู้อ่านสามารถทดลองไม่ Check ดูได้ ผู้เขียนแค่เกรงว่าสิทธิจะไม่เพียงพอเลยเลือกไว้เท่านั้น)
จากนั้นเปลี่ยนไปที่แท็บ Triggers เราสามารถกำหนดให้ Task รันตามตารางเวลาที่กำหนดได้ดังแสดง

 General ทำการตั้งชื่อ Task
 Checkbox ชื่อ Run with highest Privileges

ผู้เขียนได้กำหนดให้ Task รันทุกวันในเวลา 12:00 PM อย่าลืมเลือก Checkbox ชื่อ Enabled ไว้ด้วย ไม่อย่างนั้นแล้ว Trigger นี้จะไม่ทำงาน

 จากนั้นเลือกไปที่แท็บ Actions เราสามารถเลือกรันไปที่ไฟล์ Script อย่างเช่น Batch File ได้
โดยสร้างสคริปต์ในการ Start หรือ Stop Service เอาไว้ใน Batch File เดียวเลย
หรือจะเลือกรันคำสั่ง net ไปทีละคำสั่ง แล้วตามด้วยอาร์กิวเมนต์ในช่อง Add Arguments ดังแสดง

ช่อง Add Arguments
ช่อง Add Arguments

ทำแบบนี้จะกว่าหมดชุดของการ STOP โดยผลลัพธ์ที่ได้จะเป็นดังนี้

ชุดของการ STOP

จากนั้นผู้เขียนจะตรวจสอบว่า Reporting Service เปิดใช้งานอยู่หรือไม่ ผ่านทาง SQL Server Configuration Manager ดังแสดง 

SQL Server Configuration Manager

จากรูป หาก Reporting Service ไม่อยู่ในสถานะ Running ให้ทำการ Start Service ขึ้นมาใหม่
หลังจากนั้นผู้เขียนกลับไปที่ Task Scheduler คลิกขวาไปที่ Task ที่สร้างไว้ แล้วเลือกไปที่ Run ดังแสดง

 คลิกขวาไปที่ Task ที่สร้างไว้ แล้วเลือกไปที่ Run

เมื่อกลับไปดูใน SQL Server Configuration Manager จะพบว่า Reporting Service มีสถานะเป็น Stopped ไปเรียบร้อยแล้ว ดังแสดง

Reporting Service มีสถานะเป็น Stopped

ทั้งหมดนี้เป็นการทดสอบว่า Task สามารถ Stop Service ลงได้หรือไม่ ซึ่งปรากฏว่าสำเร็จ
จากนั้นเราจะทำการเพิ่มเติม Actions ลงไปให้ครบถ้วนสำหรับการ Restart ผลลัพธ์ที่ได้ควรเป็นดังนี้

Restart

สรุป

หากเป็นผู้เขียนจะเลือกแนวทางที่ 2 เหตุผล ก็คือ Reporting Service เป็นบริการบน Microsoft Windows ก็ควรดูแลโดย Microsoft Windows เป็นหลัก
และ การจัดเก็บ Credential ของ User จะถูกดำเนินการโดย Active Directory Database ในกรณีเป็น Domain User

และ หากเป็นกรณี Local User ก็จะจัดเก็บโดย SAM File ถึงอย่างไรก็ยังดีกว่าการเพิ่มที่จัดเก็บ Credential ของคนที่มีสิทธิสูงไว้ที่อื่นโดยไม่จำเป็น

อย่างกรณีการสร้าง Credentials ภายใต้ Database Engine (ความเห็นส่วนตัว) อีกอย่างเมื่อ Credential เหล่านั้นมีการเปลี่ยนแปลงในต้นทาง
เช่น มีการเปลี่ยน Password จากฝั่ง Active Directory หรือจาก SAM File แล้ว แต่ Credential ที่เก็บไว้ใน Database Engine ไม่เปลี่ยนตาม Script ที่ใช้สิทธิผ่าน Credential เหล่านั้นก็จะใช้งานไม่ได้