SSH বিচ্ছিন্ন হলেও command চালু রাখার উপায়
SSH বন্ধ হলে kernel SIGHUP পাঠিয়ে job থামায়। nohup, disown, tmux ও systemd-run-এর মধ্যে কোনটি কখন ব্যবহার করবেন, কমান্ডসহ সহজভাবে জানুন।
SSH বিচ্ছিন্ন হলে আপনার command কেন বন্ধ হয়ে যায়
SSH বিচ্ছিন্ন হওয়ার পর কোনো command চালু রাখতে হলে সেটিকে এমন জায়গায় চালাতে হবে, যেখানে hangup signal পৌঁছাতে পারে না। নিচের প্রতিটি পদ্ধতি এটি ভিন্নভাবে করে। তাই আগে প্রক্রিয়াটি বুঝুন।
আপনার login একটি pty (pseudo-terminal)-তে চলে। এটি একটি virtual terminal device, যা sshd আপনার session-এর জন্য server-এ তৈরি করে। এটি আপনার shell এবং সেই shell থেকে চালু করা প্রতিটি command-এর controlling terminal। এই প্রক্রিয়ার পরের ধাপগুলো জানতে login করার সময় SSH কী তৈরি করে দেখুন। TCP connection বন্ধ হলে sshd তার প্রান্ত বন্ধ করে এবং pty ধ্বংস হয়ে যায়। kernel এটিকে terminal hangup হিসেবে ধরে। তাই এটি ওই terminal-এর foreground process group এবং session leader-কে, অর্থাৎ আপনার shell-কে, SIGHUP পাঠায়। SIGHUP-এর default action হলো process বন্ধ করা। আপনার command foreground process group-এ ছিল। তাই command-টি বন্ধ হয়ে যায়।
Background job-ও নিরাপদ নয়। & দিয়ে চালু করা job নিজের process group-এ থাকে। তাই kernel সেটিকে সরাসরি signal পাঠায় না। Bash এটি করে। SIGHUP পাওয়ার পর interactive bash বন্ধ হওয়ার আগে তার job table-এর প্রতিটি job-এ SIGHUP আবার পাঠায়। আপনার দিক থেকে ফল একই দেখায়: job চলে যায় এবং log file মাঝপথে লেখা বন্ধ করে।
এখানে একটি অসমতা আছে, যা অনেককে বিভ্রান্ত করে। exit টাইপ করলে আপনার background job hangup হয় না, কারণ bash কেবল huponexit option সেট থাকলে এটি করে। Default অবস্থায় option-টি বন্ধ থাকে। কিন্তু connection বিচ্ছিন্ন হলে job-গুলো hangup হয়। আপনি terminal স্বাভাবিকভাবে বন্ধ করার পর যে job চলতে থাকে, wifi সংযোগ বিচ্ছিন্ন হলে সেটি তবুও বন্ধ হয়ে যেতে পারে।
এখান থেকে দুটি ফল আসে। এই দুটিই পুরো বিষয়টির মূল। যে process SIGHUP উপেক্ষা করে, অথবা যার কোনো controlling terminal নেই, সেটি hangup হবে না। আবার কোনো process-এর standard output যদি ধ্বংস হয়ে যাওয়া pty-র দিকেই নির্দেশ করে, তাহলে লেখার কোনো জায়গা থাকে না। Write ব্যর্থ হয়ে EIO (input/output error) দেয়, এবং অধিকাংশ program তখন বন্ধ হয়ে যায়। আপনাকে দুই দিকের সমস্যাই সমাধান করতে হবে। অনেক নির্দেশিকায় কেবল প্রথম সমস্যাটি সমাধান করা হয়। তাই অনেকে জানান, "nohup কাজ করেনি"।
আপনার connection যদি দিনে কয়েকবার বিচ্ছিন্ন হয়, সেটিও ঠিক করুন। ~/.ssh/config-এ ServerAliveInterval 60 সেট করলে পথের কোনো NAT (network address translation) timeout-এর কারণে idle session বাতিল হবে না। কোনো session একবারও খুলতে না পারা আলাদা সমস্যা এবং এর কারণও আলাদা। এই ক্ষেত্রে connection refused এবং connection timed out-এর পার্থক্য গুরুত্বপূর্ণ।
SSH সংযোগ বিচ্ছিন্ন হওয়ার পর কোন পদ্ধতিতে একটি command চালু রাখা যায়?
কাজটির গুরুত্ব অনুযায়ী সাজানো চারটি উত্তর:
nohupঅথবাsetsid: এখন শুরু করে পরে যার log পড়বেন, এমন একবারের কাজ। Output আপনাকেই redirect করতে হবে।disown: যে কাজটি ইতিমধ্যে শুরু করেছেন কিন্তু সুরক্ষিত করতে ভুলে গেছেন। এটি process-টিকে রক্ষা করে। তবে output ফিরিয়ে দিতে পারে না।tmuxঅথবাscreen: কয়েক দিন ধরে যে কাজ monitor, interrupt এবং পুনরায় চালু করতে হবে।systemd-runঅথবা একটি প্রকৃত unit file: login session শেষ হওয়ার পরও যে কাজকে চলতে হবে, যেমন ছয় ঘণ্টারrsyncঅথবা রাতভর database import।
মনে রাখার নিয়ম: কোনো কাজের কথা ভুলে গেলে সমস্যা হলে, সেটি tmux-এর নয়, systemd-এর অধীনে থাকা উচিত। tmux window এমন একটি বিষয়, যা মানুষকে মনে রাখতে হয়। একটি unit-এর name, status, log এবং restart policy থাকে। পরবর্তী ব্যক্তি কাউকে জিজ্ঞেস না করেই সেগুলো খুঁজে পেতে পারেন।
nohup and setsid: start it and walk away
nohup ./import.sh > ~/import.log 2>&1 &
echo $! > ~/import.pidnohup sets the disposition of SIGHUP to ignore and then runs your command, so the kernel's hangup arrives and does nothing. The redirect is yours to write. If you leave standard output pointing at the terminal, nohup redirects it for you into nohup.out in the current directory, falling back to $HOME/nohup.out, and prints:
nohup: ignoring input and appending output to 'nohup.out'That file is easy to lose track of, so name it yourself. $! holds the PID (process identifier) of the last background job, and saving it means you can check on the job after you log back in.
setsid attacks the same problem from the other side. It runs the command in a new session with no controlling terminal, so no terminal exists that could hang it up.
setsid --fork ./import.sh > ~/import.log 2>&1Use --fork. Without it, setsid calls setsid() in place whenever the process is not already a process group leader, which is what happens inside a shell script, and then your script sits there blocked. With --fork the behaviour is the same in a script and at the prompt.
Check what you actually got:
ps -o pid,ppid,sid,tty,stat,cmd -p "$(cat ~/import.pid)"A TTY column of ? means the process has no controlling terminal, so nothing can hang it up. Under nohup the TTY column still shows something like pts/0 while you stay connected, and becomes ? once the pty is destroyed. Both results are healthy. The job survived.
disown: ইতিমধ্যে শুরু করা job উদ্ধার করা
আপনি foreground-এ দুই ঘণ্টার একটি job শুরু করার পর এই সমস্যাটির কথা মনে করলেন। এটিকে kill করে আবার শুরু করবেন না।
# press Ctrl-Z to suspend the job first
bg
jobs -l
disown -h %1Ctrl-Z job-টিকে suspend করে, bg এটিকে background-এ চালু করে, এবং jobs -l PID-এর পাশে job number দেখায়। disown -h %1 job-টিকে এমনভাবে চিহ্নিত করে, যাতে bash এটিতে SIGHUP পাঠাবে না। সাধারণ disown %1 job-টিকে bash-এর table থেকে পুরোপুরি সরিয়ে দেয়। hangup-এর ক্ষেত্রে এর ফল একই, তবে এরপর jobs আর job-টিকে তালিকাভুক্ত করে না।
disown যা করতে পারে না, তা হলো output সরানো। Process-টি এখনও standard output হিসেবে pty ধরে রাখে। pty চলে গেলে পরবর্তী write EIO ফেরত দেয়। তাই disown সাধারণত এমন নীরব job নির্ভরযোগ্যভাবে বাঁচায়, যেমন file-এ output লেখা কোনো compile। কিন্তু বেশি output লেখা job প্রায়ই ব্যর্থ হয়। Job-টি হয় print করার জায়গা না থাকলেও টিকে থাকে, নয়তো পরবর্তী output line লেখার সময় বন্ধ হয়ে যায়।
File descriptor-এর জন্য একটি rescue tool আছে। reptyr চলমান process-কে আপনার বর্তমান terminal-এ স্থানান্তর করে। sudo apt install -y reptyr দিয়ে এটি install করুন, তারপর একটি tmux window-এর ভেতর থেকে reptyr <pid> চালান। এটি ptrace ব্যবহার করে কাজ করে। Ubuntu-তে kernel.yama.ptrace_scope = 1 দেওয়া থাকে, যা শুধু আপনার নিজের descendant process trace করার অনুমতি দেয়। তাই উত্তরাধিকারসূত্রে পাওয়া কোনো process-এর জন্য sudo reptyr <pid> প্রয়োজন। এটিকে জরুরি ব্যবহারের tool হিসেবে বিবেচনা করুন। এটিকে নিয়মিত workflow-এর ভিত্তি করবেন না।
tmux: যে কাজ আপনাকে পর্যবেক্ষণ করে পরে আবার চালিয়ে যেতে হবে
tmux (terminal multiplexer) সমস্যাটিকে অন্য স্তরে সমাধান করে। আপনার process-কে pty থেকে সুরক্ষিত করার বদলে এটি এমন একটি pty দেয়, যা আপনার SSH session-এর অন্তর্ভুক্ত নয়। tmux server ওই session-এর বাইরে চলে এবং এর ভেতরের সব কিছুর terminal-এর মালিক থাকে। আপনার SSH connection কেবল এর সঙ্গে যুক্ত একটি viewer। connection বিচ্ছিন্ন হলে server তা বুঝতে পারে না।
sudo apt update && sudo apt install -y tmux
tmux new -s importওই window-তে job শুরু করুন। তারপর detach করতে Ctrl-b এবং d চাপুন। পরে আবার login করে কাজটি চালিয়ে নিন:
tmux ls
tmux attach -t importtmux ls-এর output import: 1 windows দিয়ে শুরু হওয়া একটি line দেখানোর কথা। যদি no server running on /tmp/tmux-1000/default দেখায়, তাহলে attach করার মতো কোনো session নেই। কারণ session তৈরি হয়নি, অথবা কোনো কিছু server-টি বন্ধ করে দিয়েছে।
screen একই কাজ করে, তবে ভিন্ন keystroke ব্যবহার করে। screen -S import একটি session তৈরি করে, তারপর Ctrl-a এবং d চাপলে session থেকে detach করা যায়। screen -ls বর্তমানে থাকা session-এর তালিকা দেখায় এবং screen -r import একটি session আবার চালু করে। এখানে যেকোনো একটি tool ব্যবহার করা যায়। মানুষ সাধারণত যে বিষয়টি ভুলে যায়, সেটি হলো detach key।
কোনো সংযোগ বিচ্ছিন্ন হলেও টিকে থাকতে হবে এমন interactive কাজের জন্য multiplexer-ই উপযুক্ত পরিবেশ। তাই VPS-এ tmux-এর ভেতরে Claude Code চালানো সাধারণ setup। প্রতি কয়েক মিনিটে reconnect করা mobile network-এ phone থেকে server session পরিচালনা ব্যবহারযোগ্য করার জন্যও এটি প্রয়োজনীয়।
systemd-run: কাজটি PID 1-এর কাছে হস্তান্তর করুন
যে কাজটি কোনোভাবেই আপনার ওপর নির্ভর করবে না, সেটি init system-এর কাছে হস্তান্তর করুন।
sudo systemd-run --unit=bigsync --collect /usr/bin/rsync -aH --stats /srv/data/ /mnt/backup/এতে bigsync.service নামের একটি transient service unit তৈরি হয়। এটি নিজস্ব cgroup পায়, এর কোনো controlling terminal থাকে না, এবং আপনার login-এর সঙ্গে এর কোনো সম্পর্ক থাকে না। কমান্ডটি সঙ্গে সঙ্গে ফিরে আসে এবং Running as unit: bigsync.service প্রিন্ট করে। নিচের যেকোনো একটি উপায়ে এটি monitor করুন:
systemctl status bigsync
journalctl -u bigsync -f--collect systemd-কে বলে যে unit-টি শেষ হলে সেটি সরিয়ে ফেলতে হবে, কাজটি ব্যর্থ হলেও। এটি না থাকলে ব্যর্থ transient unit loaded অবস্থায় থেকে যায় এবং তার নামটি দখল করা থাকে। ফলে পরেরবার চালালে unit ইতিমধ্যে বিদ্যমান—এমন বার্তা দিয়ে ব্যর্থ হয়। প্রতিটি লাইনে timestamp-সহ output journal-এ যায়। /var/log/journal বিদ্যমান থাকলেই journal entry reboot-এর পরেও থাকে। তাই এটি চাইলে sudo mkdir -p /var/log/journal চালান এবং systemd-journald restart করুন।
সাধারণ user হিসেবে sudo ছাড়া systemd-run চালালে authorization-এর জন্য polkit-এর কাছে অনুরোধ যায় এবং ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units === প্রিন্ট হয়। System unit-এর জন্য sudo ব্যবহার করুন।
আপনি নিজের user manager-এর অধীনেও কাজটি চালাতে পারেন:
systemd-run --user --unit=bigsync --collect /usr/bin/rsync -aH /srv/data/ /mnt/backup/এখানে একটি গুরুত্বপূর্ণ সমস্যা আছে। আপনার per-user manager, user@1000.service, সাধারণত আপনার শেষ session শেষ হলে বন্ধ হয়ে যায়। এর সঙ্গে সব user unit-ও বন্ধ হয়ে যায়। একবার lingering চালু করুন:
loginctl enable-linger "$USER"
loginctl show-user "$USER" --property=Lingerদ্বিতীয় কমান্ডটির output হিসেবে Linger=yes প্রিন্ট হওয়া উচিত। Lingering চালু থাকলে আপনার user manager boot-এর সময় শুরু হয় এবং আপনি login করা না থাকলেও চলতে থাকে। এটি ছাড়া systemd-run --user, nohup-এর তুলনায় কোনো অতিরিক্ত সুবিধা দেয় না।
systemd-run --scope ভিন্ন একটি বিষয়। এটি command-টি foreground-এ চালায় এবং আপনার terminal-এর সঙ্গে যুক্ত থাকে। তাই এই ক্ষেত্রে এটি সহায়ক নয়।
যে কাজ একাধিকবার চালাবেন, প্রতিবার transient unit টাইপ না করে unit-টি file হিসেবে সংরক্ষণ করুন।
যে কাজ আবার চালাবেন, তার জন্য একটি স্থায়ী unit
[Unit]
Description=Nightly data sync
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
User=deploy
WorkingDirectory=/srv/data
ExecStart=/usr/local/bin/nightly-sync.shএটি /etc/systemd/system/nightly-sync.service হিসেবে সংরক্ষণ করুন, sudo systemctl daemon-reload চালান, তারপর sudo systemctl start nightly-sync দিয়ে শুরু করুন এবং journalctl -u nightly-sync দিয়ে এর configuration পড়ে দেখুন। কাজটি on demand-এর বদলে schedule অনুযায়ী চালাতে হলে সংশ্লিষ্ট .timer file যোগ করুন।
systemd service unit এবং তার timer লেখা-এ file format এবং schedule syntax সম্পূর্ণভাবে ব্যাখ্যা করা হয়েছে।
আউটপুট কোথায় যায় এবং কেন অদৃশ্য হয়ে যায়
Redirection-এর ক্রম গুরুত্বপূর্ণ। > file 2>&1 প্রথমে standard output-কে ফাইলে পাঠায়, তারপর standard error-কেও একই জায়গায় পাঠায়। 2>&1 > file উল্টোভাবে কাজ করে: standard error terminal-এ যেতে থাকে, আর যে terminal-টি অদৃশ্য হতে চলেছে, সেটিই তার গন্তব্য। Bash একই সময়ে উভয় stream-এর জন্য &> file-ও গ্রহণ করে।
দ্বিতীয় সমস্যা হলো buffering। standard output যখন terminal হয়, তখন C library প্রতিটি line flush করে। standard output যখন file হয়, তখন এটি কয়েক kilobyte-এর block buffer ব্যবহার করে। তাই tail -f ~/import.log কয়েক মিনিট কোনো output দেখায় না এবং job-টিকে বন্ধ মনে হয়। stdbuf -oL ./import.sh > ~/import.log 2>&1 দিয়ে line buffering বাধ্যতামূলক করুন, অথবা program-এর নিজস্ব switch ব্যবহার করুন, যেমন python3 -u বা grep --line-buffered।
এই pattern এড়িয়ে চলুন:
nohup ./import.sh 2>&1 | tee ~/import.log &nohup শুধু import.sh-কে সুরক্ষিত করে। অন্য কিছু নয়। tee একই pipeline-এর একটি পৃথক process, তাই hangup হলে এটিও বন্ধ হয়ে যায়। এরপর import.sh এমন একটি pipe-এ লিখতে থাকে যার কোনো reader নেই। ফলে এটি SIGPIPE গ্রহণ করে এবং থেমে যায়। পুরো pipeline-কে setsid bash -c '...'-এর ভিতরে রাখুন, অথবা সরাসরি file-এ লিখুন এবং reconnect করার পরে file-টির ওপর tail -f চালান।
বিশেষ করে rsync-এর ক্ষেত্রে আরও একটি বিষয় মনে রাখুন। --info=progress2 carriage return-এর একটি stream লেখে, যা terminal-এ সঠিক দেখায়। কিন্তু log file বা journal-এ এটি একটি বিশাল line হয়ে যায়। unattended run-এর জন্য এটি বাদ দিয়ে --stats ব্যবহার করুন।
আপনার shell-এ চলা job systemd বা cron-এর অধীনে ব্যর্থ হওয়ার কারণ
আপনার interactive shell /etc/profile, ~/.profile এবং ~/.bashrc পড়ে। তাই এতে আপনার PATH, version manager shim এবং exported variable থাকে। systemd unit এগুলোর কোনোটিই পড়ে না। cron-ও এগুলো পড়ে না। Debian ও Ubuntu-তে cron SHELL=/bin/sh এবং PATH=/usr/bin:/bin ব্যবহার করে job চালায়।
systemd-এর অধীনে লক্ষণটি হলো systemctl status, যেখানে (code=exited, status=203/EXEC) দেখানো হয়। এর অর্থ systemd ফাইলটি একেবারেই execute করতে পারেনি। কারণ path ভুল ছিল অথবা ফাইলটিতে executable permission নেই। cron-এর ক্ষেত্রে সাধারণত command not found দেখা যায়। এটি local mail-এর মাধ্যমে পাঠানো হয়, অথবা কোনো mail system ইনস্টল না থাকলে একেবারেই কোথাও পাঠানো হয় না।
অনুমান করে এক ঘণ্টা নষ্ট করার আগে environment পরীক্ষা করে নিশ্চিত হন:
sudo systemd-run --collect --wait --unit=envtest /usr/bin/env
journalctl -u envtest --no-pagerএতে আপনার job যে exact environment নিয়ে চলবে, সেটিই দেখা যাবে। এরপর পার্থক্যটি ঠিক করুন। নিজের ব্যবহৃত যেকোনো কিছুর জন্য absolute path ব্যবহার করুন। কারণ systemd bare rsync-কে নির্দিষ্ট system path list-এর ভিত্তিতে resolve করে। এটি কখনো আপনার shell-এর PATH ব্যবহার করে না। প্রয়োজনীয় variable command line-এ -p Environment="KEY=value" দিয়ে অথবা unit file-এ EnvironmentFile=/etc/default/myjob দিয়ে দিন। কোনো job-এর জন্য সত্যিই আপনার login environment দরকার হলে সেটিকে /bin/bash -lc 'my-command' হিসেবে চালান। তবে মনে রাখবেন, তখন job-টি আপনার dotfile-এর ওপর নির্ভর করবে।
ডিটাচ করা job-কে কোন বিষয়গুলো এখনও বন্ধ করে দেয়
- Reboot। reboot-এর পর
tmux-এর কোনো তথ্য টিকে থাকে না, কারণ server একটি সাধারণ process এবং session-গুলো তার in-memory state। Kernel update-এর জন্য reboot প্রয়োজন হয়। তাই যে job সহজে restart করা যায় না, সেটিকে এমন একটি unit-এ রাখুন যেটি আপনিsystemctl enableকরতে পারেন। - Out-of-memory killer।
dmesg -T | grep -i 'killed process'এই ঘটনা দেখায় এবং কোন process-কে নির্বাচন করা হয়েছে তার নামও দেখায়। ছোট VPS-এ বড় import প্রায়ই এর শিকার হয়। logindcleanup।/etc/systemd/logind.conf-এKillUserProcesses=yesসেট করা থাকলে আপনার শেষ session শেষ হওয়ার সময় অবশিষ্ট process-গুলো বন্ধ করে দেওয়া হয়। এর মধ্যেtmuxserver-ও থাকে। বর্তমান setting পরীক্ষা করতেloginctl show --property=KillUserProcessesচালান এবং আপনার user-কে এই cleanup থেকে বাদ দিতেloginctl enable-linger "$USER"ব্যবহার করুন।- Disk সম্পূর্ণ ভরে যাওয়া। আপনি session ছেড়েছেন বলে job বন্ধ হয় না। Redirect করা log filesystem পূর্ণ করে ফেললে job বন্ধ হয়। signal-কে দোষ দেওয়ার আগে
df -hচালান।
SSH সংযোগ চালু না রেখেই একটি job শুরু করা
ssh vps 'sudo systemd-run --unit=import --collect /usr/local/bin/import.sh'unit start হওয়ার সঙ্গে সঙ্গে systemd-run ফিরে আসে। তাই ssh command-ও ফিরে আসে, এবং job-টির সঙ্গে এটি চালু করা session-এর কোনো সংযোগ থাকে না। এটিই পরিষ্কার পদ্ধতি।
nohup পদ্ধতিতে আরও সতর্কতা প্রয়োজন:
ssh vps 'nohup ./import.sh > ~/import.log 2>&1 < /dev/null &'redirection ছাড়া এটি আটকে আছে বলে মনে হয়। কোনো process-এর কাছে remote command-এর standard output বা standard error থাকলে sshd channel খোলা রাখে, এবং background-এ চালানো job উভয়ই inherit করে। শুধু nohup ব্যবহার করলে সমস্যার সমাধান হয় না, কারণ nohup কেবল output terminal হলে তা redirect করে; এখানে output আপনার client-এ ফেরত পাঠানো একটি pipe। < /dev/null যোগ করলে input side-ও বন্ধ হয়। client side থেকে ssh -n একই কাজ করে।
FAQ
আমার SSH connection বিচ্ছিন্ন হলে command কেন বন্ধ হয়ে যায়?
আপনার session যে pty (pseudo-terminal) ব্যবহার করছিল, সেটি ধ্বংস হয়ে যায়। এরপর kernel ওই terminal-এর foreground process group-এ SIGHUP পাঠায়। SIGHUP-এর default action হলো process বন্ধ করা। Background job-ও বন্ধ হয়, কারণ bash exit করার আগে তার table-এর প্রতিটি job-এ আবার SIGHUP পাঠায়। SIGHUP উপেক্ষা করে এমন command, যেমন nohup দিয়ে শুরু করা command, অথবা যে command কখনো আপনার session-এর সঙ্গে যুক্তই ছিল না, যেমন systemd unit, এতে প্রভাবিত হয় না।
ছয় ঘণ্টার rsync-এর জন্য tmux নাকি systemd-run ভালো?
systemd-run। tmux session আপনার শুরু করা একটি server process-এর ওপর নির্ভর করে। তাই পরবর্তী reboot-এ এটি শেষ হয়ে যায়। এছাড়া tmux ls চালানোর কথা না জানলে অন্য কেউ এটি দেখতে পারে না। sudo systemd-run --unit=bigsync --collect /usr/bin/rsync -aH --stats /srv/data/ /mnt/backup/ চালালে state-এর জন্য systemctl status bigsync এবং output-এর জন্য journalctl -u bigsync পাওয়া যায়। পরবর্তী administrator-কে আলাদা করে না জানালেও এগুলো পাওয়া যাবে। যে কাজের সময় screen পর্যবেক্ষণ করে এতে input দেওয়া দরকার, সেখানে tmux ব্যবহার করুন।
যে job-এর output redirect করতে ভুলে গেছি, সেটি কীভাবে দেখব?
সাধারণত পারবেন না। কারণ output এমন একটি terminal-এ গিয়েছিল, যেটি এখন আর নেই। Process এখনও চললে sudo ls -l /proc/<pid>/fd দিয়ে তার open file পরীক্ষা করতে পারেন। sudo strace -p <pid> দিয়ে তার system call-ও পর্যবেক্ষণ করতে পারেন। তবে ইতিমধ্যে লেখা text আর পাওয়া যাবে না। reptyr <pid> process-টিকে একটি নতুন terminal-এ স্থানান্তর করতে পারে। Ubuntu-এর kernel.yama.ptrace_scope = 1 অনুযায়ী, process-টি আপনার নিজের child না হলে এর জন্য sudo প্রয়োজন। শুরুতেই output একটি file-এ redirect করে tail -f করার অভ্যাস করলে এই সমস্যা এড়ানো যায়।
বিচ্ছিন্ন tmux session কি reboot-এর পরেও টিকে থাকে?
না। tmux server একটি সাধারণ process। Session-গুলো তার in-memory state। তাই reboot হলে দুটিই শেষ হয়ে যায়। /etc/systemd/logind.conf KillUserProcesses=yes সেট করার পর আপনার শেষ session থেকে logout করলেও এটি বন্ধ হয়ে যায়। loginctl enable-linger "$USER" এটি প্রতিরোধ করে। Reboot-এর পর নিজে থেকে আবার চালু হতে হবে এমন কাজের জন্য একটি systemd unit লিখে সেটিতে systemctl enable করুন।
আমার script shell-এ চলে, কিন্তু systemd unit হিসেবে ব্যর্থ হয় কেন?
একটি unit /etc/profile বা ~/.bashrc পড়ে না। তাই এতে আপনার PATH-এর সংযোজন বা exported variable থাকে না। systemctl status-এ (code=exited, status=203/EXEC) দেখা গেলে বোঝায়, systemd file-টি একেবারেই execute করতে পারেনি। তাই absolute path ব্যবহার করুন এবং executable bit পরীক্ষা করুন। sudo systemd-run --collect --wait --unit=envtest /usr/bin/env চালান। journalctl -u envtest দিয়ে সেটি আবার পড়ুন। এতে আপনার job যে exact environment পায়, তা দেখা যাবে। অনুপস্থিত যা কিছু আছে, তা Environment= বা EnvironmentFile= দিয়ে সরবরাহ করুন।