SSD Nodes Learn 🎉 VPS $5.50/মাস থেকে
নির্দেশিকা Matt Connorদ্বারা Matt Connor

Linux-এ watch কমান্ড সঠিকভাবে ব্যবহার করার নিয়ম

watch ডিফল্টে প্রতি 2 সেকেন্ডে কমান্ড চালায়। interval ঠিক করুন, পরিবর্তন highlight করুন, বদলালেই exit করুন এবং pipe-এ quote দিন, যাতে watch সঠিক কমান্ড চালায়।

watch কমান্ড কী করে

watch কমান্ডটি নির্দিষ্ট বিরতিতে অন্য একটি কমান্ড আবার চালায় এবং একই স্ক্রিন এলাকায় তার আউটপুট নতুন করে দেখায়। ডিফল্ট বিরতি হলো দুই সেকেন্ড। কোনো মান পরিবর্তন হওয়ার অপেক্ষায় থাকলে এটি ব্যবহার করুন: যেমন কোনো disk পূর্ণ হওয়া, কোনো container স্থিতিশীল হওয়া, কোনো certificate renewal সম্পন্ন হওয়া বা কোনো queue খালি হওয়া।

watch procps-ng-এর অংশ এবং নতুন Ubuntu বা Debian VPS-এ procps package-এর অংশ হিসেবে এটি আগে থেকেই installed থাকে। নিচের কোনো flag ব্যবহারের আগে আপনার version পরীক্ষা করুন, কারণ কার্যকর দুটি option সম্প্রতি যোগ হয়েছে।

watch --version

Ubuntu 24.04-এ এটি watch from procps-ng 4.0.4-এর মতো একটি line দেখায়। এবার সবচেয়ে সহজ কার্যকর উদাহরণটি দেখুন।

watch df -h /

স্ক্রিন পরিষ্কার হয়ে একটি header line, একটি ফাঁকা line এবং তারপর df -h /-এর output দেখায়:

Every 2.0s: df -h /                          server1: Sun Aug  9 10:21:44 2026

বাম পাশে interval এবং watch যে exact command চালাচ্ছে তা দেখা যায়। ডান পাশে hostname এবং বর্তমান সময় দেখা যায়। Clock-টি গুরুত্বপূর্ণ, কারণ নিচের সংখ্যাগুলো পরিবর্তিত না হলেও এটি প্রমাণ করে যে স্ক্রিন refresh হচ্ছে। বের হতে Ctrl+C চাপুন।

watch terminal-এ যতটুকু জায়গায় একটি frame দেখানো যায়, ততটুকুই আঁকে। দীর্ঘ line wrap হয়; -w সেগুলো truncate করে। আর bottom row-এর পরের কোনো বিষয় একেবারেই দেখানো হয় না। Frame-এর ভেতরে scrollback নেই, কারণ প্রতিটি cycle আগের frame-টি overwrite করে। এই একটি বিষয়ই watch কোন কাজে উপযোগী, তা বেশির ভাগ ক্ষেত্রে নির্ধারণ করে।

watch কত ঘন ঘন কমান্ডটি আবার চালাবে?

দুই সেকেন্ড শুধু একটি ডিফল্ট মান। মানটি কত দ্রুত পরিবর্তিত হয় এবং একবার চালাতে কতটা খরচ হয়, তার ভিত্তিতে interval নির্বাচন করুন।

  • -n 0.5 নিয়মিত পরিবর্তিত হওয়া counter-এর জন্য, যেমন ss -s বা কোনো interface-এর byte count। watch গ্রহণ করতে পারে এমন সর্বনিম্ন interval হলো 0.1 seconds।
  • -n 30 বা -n 60 disk এবং certificate-এর জন্য। এক দিনে পূর্ণ হওয়া filesystem-এর জন্য প্রতি মিনিটে ত্রিশটি frame প্রয়োজন হয় না।

watch কমান্ডটি চালায়, সেটি শেষ হওয়া পর্যন্ত অপেক্ষা করে, তারপর interval অনুযায়ী অপেক্ষা করে। এই gap-এর সঙ্গে command-এর runtime-ও যোগ হয়। তাই -n 2-এর অধীনে কোনো কমান্ড চালাতে আট সেকেন্ড লাগলে প্রতি দশ সেকেন্ডে একটি frame পাবেন এবং পুরো সময় মেশিনটি ব্যস্ত থাকবে। -p (--precise) যোগ করলে watch পরিবর্তে প্রতি interval seconds অন্তর একটি run শুরু করার লক্ষ্য রাখে। এটি একটি run শুরু হওয়া থেকে পরবর্তী run শুরু হওয়া পর্যন্ত সময় গণনা করে।

আপনি সব সময় ভিন্ন একটি default চাইলে shell profile-এ WATCH_INTERVAL export করুন। স্পষ্টভাবে দেওয়া -n এখনও এর চেয়ে অগ্রাধিকার পাবে। আপনার build ওই variable পড়ছে কি না নিশ্চিত করতে watch --help চালান।

-d দিয়ে কী পরিবর্তন হয়েছে তা হাইলাইট করুন

একই ধরনের টেক্সটের দীর্ঘ তালিকা দেখে কোন field-এর অবস্থান বদলেছে তা খুঁজে বের করা কঠিন। -d (--differences) এই কাজটি আপনার হয়ে করে।

watch -n 30 -d 'df -h / /var'

আগের frame-এর তুলনায় যেসব character আলাদা, সেগুলো reverse video-তে দেখানো হয়। তাই Use% cell সরলেই সেটি সঙ্গে সঙ্গে আলোকিত হয়, আর বাকি সবকিছু অপরিবর্তিত থাকে। /var যদি আলাদা filesystem না হয়, তাহলে root filesystem দুবার তালিকাভুক্ত হবে। এতে সিস্টেমটি কীভাবে partition করা হয়েছে তা দ্রুত বোঝা যায়।

এই তুলনা অবস্থানভিত্তিক। অর্থাৎ, watch নতুন frame-এর প্রতিটি line-কে পুরোনো frame-এর সঙ্গে character ধরে মিলিয়ে দেখে। যেসব output-এর column-এর প্রস্থ পরিবর্তিত হয়, সেগুলো প্রায় সম্পূর্ণ হাইলাইট হবে। তাই স্থির layout ব্যবহার করে এমন command বেছে নিন। বর্তমান procps-ng-ও watch --differences=permanent গ্রহণ করে। এটি শুধু সর্বশেষ পরিবর্তন নয়, আগে কখনও পরিবর্তিত হওয়া প্রতিটি অবস্থান হাইলাইট করে রাখে। নির্ভর করার আগে watch --help দিয়ে এটি নিশ্চিত করুন।

কীভাবে আউটপুট পরিবর্তিত হলে watch থেকে বের হব?

-g (--chgexit) আগের রান থেকে আউটপুটে প্রথম পার্থক্য দেখা গেলেই watch বন্ধ করে। আপনার prompt ফিরে আসে, তাই একই লাইনে এর পরে কিছু লিখতে পারেন।

watch -n 10 -g 'systemctl is-active myapp' ; echo 'state changed'

এই flag-টি watch-কে “deploy সম্পন্ন হলে আমাকে জানান” ধরনের টুলে পরিণত করে। তবে এতে একটি সমস্যা আছে, যা প্রায় সবার ক্ষেত্রেই ঘটে: তুলনাটি পুরো আউটপুটের ওপর করা হয়। তাই আউটপুটে কোনো clock বা PID (process identifier) থাকলে প্রথম refresh-এই তা বদলে যায় এবং watch সঙ্গে সঙ্গে বন্ধ হয়ে যায়। systemctl status myapp অতিবাহিত সময় ও memory usage দেখায়, তাই এতে -g ব্যবহার করা অর্থহীন। আপনি যে একমাত্র স্থির তথ্যের অপেক্ষায় আছেন, command-টি সেটিতে সীমিত করুন; systemctl is-active সেটিই দেয়।

নতুন procps-ng-তে বিপরীত পরীক্ষা, --equexit <cycles>, যোগ হয়েছে। নির্দিষ্ট সংখ্যক cycle ধরে আউটপুট অপরিবর্তিত থাকলে এটি watch থেকে বের হয়। এর অর্থ হলো, “এটি কখন আর পরিবর্তিত হচ্ছে না, আমাকে জানান।” watch --help পরীক্ষা করুন, কারণ পুরোনো build-এ এটি নেই।

watch কেন pipe এবং glob উপেক্ষা করে?

watch-এ একবার হলেও এই সমস্যায় সবাই পড়েন। এর কারণ watch-এ নয়, আপনার shell-এ।

watch docker compose ps | grep web

আপনার interactive shell কোনো কমান্ড চালানোর আগে পুরো line পড়ে এবং pipe-এ line-টি ভাগ করে। এটি watch docker compose ps চালায় এবং watch-এর নিজস্ব screen output grep-এ পাঠায়। watch আর terminal-এ লিখছে না। তাই display ভাঙা বা ফাঁকা দেখা যায়, এবং grep container list-এর পরিবর্তে redraw output filter করে।

পুরো pipeline-টি quote করুন, যাতে এটি একটি argument হিসেবে পৌঁছায়।

watch 'docker compose ps | grep web'

watch ওই string sh -c-এ পাঠায়, এবং সেই shell প্রতিটি cycle-এ একবার pipeline চালায়। Glob-এর ক্ষেত্রেও একই নিয়ম প্রযোজ্য, তবে লক্ষণটি কম স্পষ্ট।

watch ls -l /var/log/*.log
watch 'ls -l /var/log/*.log'

প্রথম line-টি Enter চাপার সময় আপনার shell-এ glob একবার expand করে। এরপর watch স্থির filename-এর list পুনরায় চালায়। তাই এক মিনিট পরে তৈরি হওয়া log file আর দেখা যায় না। দ্বিতীয় line-টি glob watch-এর কাছে পাঠায়। watch প্রতিটি cycle-এ sh-এর ভিতরে glob expand করে। ফলে নতুন file নিজে থেকেই দেখা যায়।

Quote-এর মাধ্যমে variable বা command substitution কখন evaluate হবে, সেটিও নির্ধারিত হয়। watch "echo $(date)" আপনার shell-এ একবার date চালায় এবং এরপর একই স্থির string বারবার echo করে। watch 'echo $(date)' প্রতিটি cycle-এ date চালায়। Single quote-এর অর্থ পরে evaluate করা। Double quote-এর অর্থ এখন evaluate করা।

ওই sh -c-এর আরও দুটি ফল আছে:

  • এর ভিতরে alias এবং shell function থাকে না। watch ll, sh: 1: ll: not found দিয়ে ব্যর্থ হয়, কারণ sh -c আপনার .bashrc পড়ে না। আসল command লিখুন, অথবা interactive PATH-এ থাকা binary-এর সম্পূর্ণ path দিন।
  • Standard error capture করা গুরুত্বপূর্ণ। Error text frame-এর মধ্যে বিন্যস্তভাবে দেখাতে চাইলে quote-এর ভিতরে 2>&1 রাখুন; এতে error text frame-এর বাইরে ছড়িয়ে পড়বে না।

Quote করা জটিল হয়ে গেলে -x (--exec) ব্যবহার করুন। এটি sh -c-এর মাধ্যমে নয়, সরাসরি command চালায়। Space থাকা argument সহজে দেওয়া যায়। তবে pipe এবং glob পুরোপুরি কাজ বন্ধ করে দেয়, কারণ সেগুলো interpret করার জন্য কোনো shell থাকে না।

Privileges-এর ক্ষেত্রেও একই নিয়ম প্রযোজ্য, কারণ watch একটি সাধারণ process। watch 'sudo ss -tulpn' এমন password prompt দেখায় যা আপনি দেখতে বা তাতে input দিতে পারবেন না। পরিবর্তে sudo watch 'ss -tulpn' চালান। মনে রাখবেন, এরপর Ctrl+C চাপা পর্যন্ত পুরো loop root হিসেবে চলবে।

VPS-এ পর্যবেক্ষণ করার মতো চারটি বিষয়

পূর্ণ হয়ে আসা একটি disk

watch -n 30 -d 'df -h / /var'

df kernel-এর কাছে আগে থেকেই থাকা পরিসংখ্যান চায়, তাই এটি বারবার চালালেও খরচ খুব কম। কিন্তু du -sh /var/log তা নয়, কারণ প্রতিটি cycle-এ এটি tree-এর প্রতিটি file পরীক্ষা করে। watch-এর অধীনে এটি disk ক্রমাগত পড়ে এবং যে মেশিনটি আপনি নির্ণয় করার চেষ্টা করছেন সেটিকে ধীর করে দেয়। du একবার চালান, অথবা ncdu ব্যবহার করুন। এরপর df-কে watch-এর অধীনে রেখে দেখুন সংখ্যাটি এখনও বাড়ছে কি না।

বারবার restart হওয়া একটি container

cd /srv/myapp
watch -n 5 -d 'docker compose ps'

status column-এ প্রতিটি container কতক্ষণ ধরে চালু আছে তা দেখা যায়। crash loop-এ থাকা container বারবার "Up 2 seconds"-এ ফিরে যায়, এবং -d তা এক নজরেই স্পষ্ট করে। আগে directory পরিবর্তন করুন, কারণ যে shell থেকে watch শুরু হয়েছে, watch সেই shell-এর working directory ব্যবহার করে এবং docker compose-এর project directory প্রয়োজন। watch জানায় যে restart হচ্ছে। docker compose logs -f web জানায় কেন হচ্ছে। কারণ জানা হয়ে গেলে উত্তরটি container নিজে restart করার জন্য একটি Compose healthcheck হিসেবে নির্ধারণ করুন, যাতে কাউকে বসে screen-এর দিকে তাকিয়ে থাকতে না হয়।

certificate renewal সম্পন্ন হওয়া

sudo -i
watch -n 60 -g 'openssl x509 -noout -enddate -in /etc/letsencrypt/live/example.com/fullchain.pem'

command-টি একটি line, notAfter=Nov 7 09:14:22 2026 GMT, এবং অন্য কিছু print করে না। তাই file-টি renewed file দিয়ে প্রতিস্থাপিত হলেই -g ঠিক সেই সময়ে সক্রিয় হয়। /etc/letsencrypt/live-এর অধীন file-গুলো শুধু root পড়তে পারে, তাই এটি root shell-এ চলে। মনে রাখুন, এটি disk-এ থাকা certificate পর্যবেক্ষণ করে। চলমান web server reload না হওয়া পর্যন্ত পুরোনো certificate memory-তে রাখে। তাই বাস্তবে কী serve হচ্ছে তা echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate দিয়ে পরীক্ষা করুন এবং public host-এর বিরুদ্ধে ওই command-টি দুই second interval-এ চালাবেন না। renewal নিজেই একটি systemd service ও timer-এর দায়িত্বে থাকে, এবং systemctl list-timers জানায় এটি পরবর্তীবার কখন চলবে।

একটি queue খালি হওয়া

watch -n 15 'postqueue -p | tail -n 1'

এটি -- 24 Kbytes in 6 Requests.-এর মতো একটি summary line print করে, অথবা কাজ শেষ হলে Mail queue is empty print করে। একই পদ্ধতি যেকোনো গণনাযোগ্য queue-এর ক্ষেত্রে কাজ করে: watch -n 5 'find /srv/queue/incoming -type f | wc -l'

এখানে watch-এর সীমা স্পষ্ট হয়। এটি একটি frame-কে তার আগের frame-এর সঙ্গে তুলনা করে এবং কোনো condition পরীক্ষা করতে পারে না। তাই "count শূন্যে পৌঁছেছে"—এ কথা এটি কখনো জানাতে পারে না। সাধারণ shell loop তা করতে পারে। প্রতিটি pass-এ count capture করার জন্য command substitution ব্যবহার করুন:

until [ "$(find /srv/queue/incoming -type f | wc -l)" -eq 0 ]; do sleep 5; done; echo 'queue drained'

watch কমান্ড যখন সঠিক টুল নয়

watch আগের রানটির কোনো তথ্য মনে রাখে না এবং কমান্ডটি কী কাজ করে সে সম্পর্কেও জানে না। df-এর জন্য এটি যথেষ্ট। তবে 4টি পরিস্থিতিতে এটি সঠিক পছন্দ নয়।

  • লগ। watch একটি নির্দিষ্ট ফ্রেম বারবার আঁকে। তাই দুইটি cycle-এর মধ্যে প্রদর্শিত হয়ে স্ক্রল করে চলে যাওয়া লাইনগুলো হারিয়ে যায়। journalctl -fu nginx অথবা tail -f ব্যবহার করুন। এগুলো লেখা হওয়ার সঙ্গে সঙ্গে নতুন লাইন stream করে।
  • ব্যয়বহুল কমান্ড। du -sh / অথবা ব্যস্ত database-এ চালানো কোনো query যেকোনো interval-এ স্থায়ী background load তৈরি করে। কারণ watch সেটি বারবার চালু করতে থাকে।
  • যে কোনো side effect-যুক্ত কাজ। যে কমান্ড write, post, restart বা install করে, সেটি প্রতিটি cycle-এ আবার একই কাজ করবে। প্রতি 2 সেকেন্ডে একটি API-তে curl চালালে দিনে 43,200টি request হয়। এর ফলে free API key suspended হয়ে যেতে পারে।
  • দীর্ঘস্থায়ী check। watch আপনার terminal-এ চলে এবং session শেষ হলে বন্ধ হয়ে যায়। এটি কাউকে alert করে না এবং laptop বন্ধ করার পরে কোনো history রাখে না। এর জন্য Uptime Kuma-এর মতো প্রকৃত status monitor ব্যবহার করুন, অথবা server-এ চলমান একটি scheduled check ব্যবহার করুন।

সীমাটি আসলে সময়ের। একটি নির্দিষ্ট ঘটনা ঘটার অপেক্ষায় আপনি যে 10 মিনিট ব্যয় করেন, watch তার জন্য উপযুক্ত। আগামীকালও যে check চলতে হবে, সেটি scheduled timer বা প্রকৃত monitor-এর দায়িত্ব।

SSH-এ থাকলে tmux-এর ভিতরে watch চালান

SSH-এর মাধ্যমে watch যতটা নির্ভরযোগ্য, তা connection-এর স্থায়িত্বের ওপর নির্ভর করে। সংযোগ বিচ্ছিন্ন হলে আপনার shell SIGHUP পায় এবং watch-ও বন্ধ হয়ে যায়। tmux এই সমস্যা সমাধান করে। এ কারণেই remote server-এ watch কার্যকরভাবে ব্যবহার করা যায়।

tmux new -As ops
watch -n 30 -d 'df -h /'

Detach করতে Ctrl+b তারপর d চাপুন। Loop server-এ চলতে থাকবে। পরে tmux attach -t ops দিয়ে আবার সংযোগ করলে frame তখনও update হতে থাকবে; header-এর clock তা নিশ্চিত করবে। Window split করলে এক পাশে watch এবং অন্য পাশে journalctl -f রাখতে পারবেন। এটাই tmux-ভিত্তিক terminal workbench-এর মূল ধারণা। একই প্রশ্ন একসঙ্গে একাধিক server-এর ক্ষেত্রে প্রযোজ্য হলে wall of watch panes ব্যবহার না করে একাধিক Linux server পরিচালনার জন্য তৈরি tool ব্যবহার করুন।

এখানে উদ্ধৃত screen-গুলো উদাহরণস্বরূপ দেখানো হয়েছে। Distribution এবং procps-ng release অনুযায়ী column layout ও version string আলাদা হতে পারে। তাই আপনার build-এ সত্যিই কোন flag আছে তা জানতে নিজের machine-এ man watch পড়ুন।

FAQ

watch mycmd | grep foo-এ pipe কেন কাজ করে না?

watch mycmd | grep foo চালু হওয়ার আগেই আপনার shell pipe-এ লাইনটি ভাগ করে। ফলে grep-এ watch mycmd | grep foo-এর নিজস্ব screen output পাঠানো হয়, কিন্তু command-এর output আর filter করা হয় না। পুরো pipeline-টি quote করুন: watch 'mycmd | grep foo'watch mycmd | grep foo ওই একক argument sh -c-এর কাছে পাঠায়, আর সেটি প্রতিটি cycle-এ pipeline চালায়। একই নিয়ম globs এবং command substitution-এর ক্ষেত্রেও প্রযোজ্য।

watch mycmd | grep foo-এর সঙ্গে কোন interval ব্যবহার করব?

মানটি কত দ্রুত পরিবর্তিত হয় এবং একবার চালাতে কত resource লাগে, তার সঙ্গে interval মিলিয়ে নিন। দ্রুত পরিবর্তনশীল counter-এর জন্য half a second উপযুক্ত, আর watch mycmd | grep foo গ্রহণ করে এমন সর্বনিম্ন interval হলো 0.1 seconds। Disk এবং certificate-এর জন্য Thirty to sixty seconds উপযুক্ত। -p না দিলে command চালানোর সময় gap-এর সঙ্গে যোগ হয়। তাই -n 1-এর অধীনে ধীর command একটির পর একটি চলে এবং কখনো বিরতি দেয় না।

watch mycmd | grep foo কি log file অনুসরণ করতে পারে?

না। watch mycmd | grep foo একটি frame redraw করে এবং কোনো history সংরক্ষণ করে না। তাই দুটি cycle-এর মাঝখানে আসা এবং পরে screen থেকে সরে যাওয়া যেকোনো line স্থায়ীভাবে হারিয়ে যায়। নতুন line আসার সঙ্গে সঙ্গে journalctl -fu <unit> এবং tail -f সেগুলো stream করে, যা log-এর জন্য প্রয়োজন। Disk percentage বা queue length-এর মতো বর্তমান state থাকা মানের জন্য watch mycmd | grep foo ব্যবহার করুন।

আমি যে ঘটনার জন্য অপেক্ষা করছি, সেটি ঘটলে watch mycmd | grep foo-কে কীভাবে বন্ধ করব?

-g (--chgexit) ব্যবহার করুন এবং এমন একটি command দিন, যার output ওই ঘটনা না ঘটা পর্যন্ত অপরিবর্তিত থাকে। Clock বা PID-সহ output প্রথম refresh-এই পরিবর্তিত হয় এবং সঙ্গে সঙ্গে exit করে। তাই systemctl is-active myapp কাজ করে, কিন্তু systemctl status myapp কাজ করে না। Count শূন্যে পৌঁছানোর মতো বাস্তব condition-এর জন্য shell until loop ব্যবহার করুন, কারণ watch mycmd | grep foo শুধু output পরিবর্তিত হয়েছে কি না তা শনাক্ত করতে পারে।

আমার shell-এ কাজ করা কোনো কিছুর জন্য watch mycmd | grep foo কেন command not found দেখায়?

watch mycmd | grep foo command-টি sh -c-এর কাছে পাঠায়। ওই shell .bashrc পড়ে না, তাই আপনার aliases এবং shell functions সেখানে থাকে না। বার্তাটি সাধারণত sh: 1: ll: not found হয়। প্রকৃত command সরাসরি লিখুন, অথবা এমন binary-এর full path ব্যবহার করুন, যা শুধু আপনার interactive PATH-এ রয়েছে।