Tuesday, February 3, 2026

PM2-г Ubuntu дээр бүрэн устгах хэдэн алхам байна

 PM2-г Ubuntu дээр бүрэн устгах хэдэн алхам байна. Энэ нь зөвхөн програмыг устгахгүй, мөн лог файлууд болон тохиргоог устгана, иймээс диск чөлөөлөхөд тохиромжтой.


1️⃣ PM2 процессыг зогсоох

pm2 kill
  • Бүх PM2 процессуудыг зогсооно.


2️⃣ PM2-г uninstall хийх

sudo npm uninstall -g pm2
  • PM2-г глобал түвшинд uninstall хийж байна.


3️⃣ PM2 тохиргоо, лог файлуудыг устгах

rm -rf ~/.pm2
  • ~/.pm2 хавтас дотор:

    • logs/ → бүх stdout/stderr log

    • dump.pm2 → процессын snapshot

    • бусад config файлууд бүгд устна


4️⃣ (Optional) PM2 logrotate module-г устгах

Хэрвээ суулгасан бол:

pm2 uninstall pm2-logrotate

5️⃣ Диск зайг шалгах

df -h
  • /home хавтасны зай чөлөөлөгдсөн эсэхийг харах.


⚠️ Санамж:

  • Энэ аргаар PM2 бүх тохиргоо, лог, процессыг устгана.

  • Хэрвээ ирээдүйд дахин ашиглах гэж байгаа бол зөвхөн лог файлуудыг truncate хийх нь илүү аюулгүй арга.

PM2 лог файлуудыг ирээдүйд автомат ротаци хийж, зай дүүрэхээс сэргийлэх тохиргоог ингэж хийх боломжтой

 PM2 лог файлуудыг ирээдүйд автомат ротаци хийж, зай дүүрэхээс сэргийлэх тохиргоог ингэж хийх боломжтой:


1️⃣ PM2 лог ротаци тохируулах

PM2 нь log rotate module-тай. Суулгаж тохируулах:

pm2 install pm2-logrotate

2️⃣ Log ротацигийн үндсэн тохиргоо

# Лог файлын хэмжээг 100MB-с хэтэрвэл шинэчлэх pm2 set pm2-logrotate:max_size 100M # Хуучин log файлуудыг 7 хоног хадгалах pm2 set pm2-logrotate:retain 7 # Ротаци хийх давтамж (минут) pm2 set pm2-logrotate:rotateInterval '0 0 * * *' # Old logs-г автоматаар цэвэрлэх pm2 set pm2-logrotate:compress true

💡 Тайлбар:

  • max_size → нэг log файлын хамгийн их хэмжээ

  • retain → хэд хоногийн log хадгалах

  • rotateInterval → cron хэлбэрээр давтамж (энд өдөрт нэг удаа)

  • compress → хуучин log-ыг zip хийж хадгалах


3️⃣ PM2-г дахин эхлүүлэх (лог ротаци ажиллуулахын тулд)

pm2 reload all

ubuntu host хэр хэмжээний hdd sdd зарцуулсан байгааг яаж харах вэ?

 Ubuntu дээр таны HDD/SSD-д хэдэн хэмжээний зай ашиглагдаж, хэдэн нь чөлөөтэй байгааг харах хэд хэдэн арга бий. Би хамгийн энгийн, үр дүнтэй аргуудыг зааж өгье:


1️⃣ df командыг ашиглах (Disk Free)

Таны файлын системийн зай хэр ашиглагдаж байгааг харуулна.

df -h
  • -h → human-readable, хүн ойлгох хэмжээ (GB, MB) дээр харуулна.

  • Үр дүнгийн жишээ:

Filesystem Size Used Avail Use% Mounted on /dev/sda1 50G 20G 28G 42% / tmpfs 3.9G 0 3.9G 0% /dev/shm /dev/sdb1 100G 60G 35G 65% /data

Тайлбар:

  • Size – нийт хэмжээ

  • Used – хэрэглэсэн хэмжээ

  • Avail – чөлөөтэй зай

  • Use% – ашиглалтын хувь


2️⃣ lsblk командыг ашиглах (Disk Devices)

Хард болон SSD-д хамаарах блокуудын мэдээллийг харуулна:

lsblk -f
  • NAME → диск эсвэл партишн нэр

  • SIZE → нийт хэмжээ

  • MOUNTPOINT → хаана холбогдсон (mount) байгааг харуулна

  • FSTYPE → файлын системийн төрөл (ext4, ntfs гэх мэт)

Жишээ:

NAME FSTYPE LABEL MOUNTPOINT SIZE sda ├─sda1 ext4 / 50G sdb └─sdb1 ext4 /data 100G

3️⃣ du командыг ашиглах (Folder-wise usage)

Нэг хавтас эсвэл бүх систем дээр хэдэн хэмжээний зай ашиглагдаж байгааг харах:

du -sh /path/to/folder

Жишээ: root хавтасны хэмжээг харах:

sudo du -sh /*
  • -s → summary (нэгтгэсэн дүн)

  • -h → human-readable


4️⃣ График хэрэгсэл ашиглах (опцион)

Ubuntu Desktop бол Disk Usage Analyzer (baobab) ашиглаж болно:

sudo apt install baobab baobab
  • Энэ нь графикаар диск ашиглалт харуулна, том файлуудыг хурдан тодорхойлно.


💡 Тэмдэглэл:

  • df нь файлын системийн хэмжээг харуулдаг.

  • lsblk нь диск/SSD-н физик хэмжээ, партишн-г харуулдаг.

  • du нь тухайн хавтасны зай хэр ашиглагдаж байгааг харуулна.

Monday, February 2, 2026

өөрийн веб хуудасыг facebook share яаж хийх вэ? next.js ашиглан


* /api/og-images/route.tsx

import { ImageResponse } from 'next/og';

export async function GET(request: Request) {
    // URL parse
    const { searchParams } = new URL(request.url);
    // ?title=Hello
    const title = searchParams.get('title') ?? 'Default гарчиг';

    return new ImageResponse(
        <div style={{ fontSize: 60, background: '#000', color: '#fff' }}>
            {title || `Миний гарчиг`}
        </div>,
        {
            width: 1200,
            height: 600,
        },
    );
}

* page.tsx

 import { Metadata } from 'next';

import HomeSections from './sections';

export async function generateMetadata({
    params,
}: {
    params: { slug: string };
}): Promise<Metadata> {
    // const article = await getArticle(params.slug); // DB / API

    return {
        title: `article.title`,
        description: `article.summary`,
        openGraph: {
            title: `article.title`,
            description: `article.summary`,
            url: `https://example.com/article/${params.slug}`,
            siteName: 'My Website',
            images: [
                {
                    url: `/api/og-images?title=Hello`,
                    width: 1200,
                    height: 600,
                },
            ],
            locale: 'mn_MN',
            type: 'article',
        },
    };
}

export default function HomePage() {
    return <HomeSections />;
}


* sections.tsx

'use client';

import { postRequestOptions } from '@/libs/helpers/networker';
import { useEffect, useState } from 'react';

export default function HomeSections() {
    const [accessToken, setAccessToken] = useState<string | null>(null);

    useEffect(() => {
        // Facebook SDK script нэмэх
        const loadFbSdk = () =>
            new Promise<void>((resolve) => {
                ((d, s, id) => {
                    const fjs = d.getElementsByTagName(s)[0];
                    if (d.getElementById(id)) return resolve();
                    const js = d.createElement(s) as HTMLScriptElement;
                    js.id = id;
                    js.src = 'https://connect.facebook.net/en_US/sdk.js';
                    js.onload = () => resolve();
                    d.body.appendChild(js);
                })(document, 'script', 'facebook-jssdk');
            });

        // SDK init
        loadFbSdk().then(() => {
            (window as any).FB.init({
                appId: process.env.NEXT_PUBLIC_FB_APP_ID,
                cookie: true,
                xfbml: false,
                version: 'v19.0',
            });
        });
    }, []);

    // Login function
    const fbLogin = () => {
        (window as any).FB.login(
            (response: any) => {
                if (response.authResponse) {
                    const accessToken = response.authResponse.accessToken;
                    console.log('User Access Token:', accessToken);
                    // Backend руу дамжуулахад ашиглана
                    setAccessToken(accessToken);
                } else {
                    console.log(
                        'User cancelled login or did not fully authorize.',
                    );
                    setAccessToken(null);
                }
            },
            { scope: 'public_profile,email,user_posts' },
        ); // user_posts scope зөвхөн тест токен дээр ажиллана
    };

    // Share function
    const shareArticle = (articleUrl: string) => {
        // const linkedMessage = `${articleUrl}`;
        // const shareUrl =
        //     'https://www.facebook.com/sharer/sharer.php?quote="hello"&u=' +
        //     encodeURIComponent(linkedMessage);
        // window.open(shareUrl, '_blank', 'width=600,height=400');
        const url = encodeURIComponent(`https://news.mn/r/2847199/`);
        window.open(
            `https://www.facebook.com/sharer/sharer.php?u=${url}`,
            '_blank',
            'width=600,height=500',
        );
    };

    const checkSharedPosts = async (articleUrl: string) => {
        fetch(
            '/api/check-fb-posts',
            postRequestOptions({
                accessToken,
                siteUrl: articleUrl,
            }),
        )
            .then((res) => {
                return res.json();
            })
            .then((data) => {
                console.log('checkSharedPosts:', data);
            })
            .catch((err) => {
                console.error('checkSharedPosts:', err);
            });
    };

    return (
        <div className="flex flex-col justify-center">
            <div>
                {accessToken ? (
                    <div>Нэвтэрсэн :)</div>
                ) : (
                    <div>Нэвтрээгүй (:</div>
                )}
            </div>
            <button
                className="bg-indigo-700 text-gray-300 text-md p-4 cursor-pointer"
                onClick={fbLogin}
            >
                Login with Facebook
            </button>
            <button
                className="bg-indigo-700 text-gray-300 text-md p-4 cursor-pointer"
                onClick={() =>
                    shareArticle('https://itissandboxbro.duckdns.org/admin')
                }
            >
                Share content on Facebook
            </button>
            <button
                className="bg-indigo-700 text-gray-300 text-md p-4 cursor-pointer"
                onClick={() =>
                    checkSharedPosts('https://itissandboxbro.duckdns.org/admin')
                }
            >
                Check out the posts shared on Facebook
            </button>
        </div>
    );
}