SSD Nodes Learn 🎉 VPS $5.50/மாதம் முதல்
கல்வி வழிகாட்டிகள் Matt Connorஆல் Matt Connor · புதுப்பிக்கப்பட்டது 2026-08-13

Bash history expansion: !! மற்றும் !$ பயன்படுத்துவது

Bash history-ல் !! மூலம் முந்தைய கட்டளையை மீண்டும் இயக்கலாம் மற்றும் !$ மூலம் கடைசி argument-ஐப் பெறலாம். கட்டளையை இயக்கும் முன் :p பயன்படுத்தி சரிபார்க்கும் முறையை அறியுங்கள்.

Bash history expansion-ன் செயல்பாடு

Bash history expansion என்பது, ஒரு கட்டளையை இயக்குவதற்கு முன்பு, உங்கள் shell history-ல் உள்ள முந்தைய கட்டளை வரியை மீண்டும் கட்டமைக்கிறது. !! முந்தைய கட்டளையை மீண்டும் இயக்கும். !$ முந்தைய கட்டளையின் கடைசி argument-ஐச் சேர்க்கும். இந்த மாற்றீடு உரை சார்ந்தது (textual), மேலும் bash வரியைச் சொற்களாகப் பிரிப்பதற்கு முன்பே இது நடக்கும். எனவே, நீங்கள் முதலில் தட்டச்சு செய்த அதே எழுத்துக்களே மீண்டும் கிடைக்கும்.

ஒரு server-ல் நீங்கள் செய்யும் பெரும்பாலான பணிகளுக்குக் கீழே உள்ள ஆறு வடிவங்கள் போதுமானவை:

  • !! முந்தைய முழு வரியையும் மீண்டும் இயக்கும், sudo !! அதை root உரிமையுடன் மீண்டும் இயக்கும்.
  • !$ என்பது முந்தைய வரியின் கடைசி argument ஆகும்.
  • !* என்பது முந்தைய வரியின் அனைத்து argument-களும் ஆகும்.
  • !n என்பது n என்ற எண்ணைக் கொண்ட history entry-ஐ இயக்கும், !-n நீங்கள் இருக்கும் இடத்திலிருந்து பின்னோக்கி எண்ணும்.
  • !string என்பது string-ல் தொடங்கும் மிகச் சமீபத்திய கட்டளையை இயக்கும்.
  • ^old^new முந்தைய வரியில் உள்ள முதல் old-ஐ new கொண்டு மாற்றி மீண்டும் இயக்கும்.

கீழே உள்ள அனைத்தும் உங்கள் சொந்த server-ல் உள்ள interactive prompt-ல் தட்டச்சு செய்யப்பட வேண்டும். Scripts-ல் history expansion முடக்கப்பட்டிருக்கும், இதைப் பற்றி கடைசிப் பகுதியில் விளக்கப்பட்டுள்ளது.

நீளமான ஒரு path, ஒருமுறை தட்டச்சு செய்தல்

இதுவே உங்களுக்குப் பயன் தரும் ஒரு சூழல். நீங்கள் ஒரு release directory-ஐத் தயார் செய்கிறீர்கள், அந்தப் பாதை மிகவும் நீளமாக இருப்பதால், அதை மீண்டும் தட்டச்சு செய்வது பிழைகளுக்கு வழிவகுக்கும்.

sudo mkdir -p /srv/www/app/releases/2026-08-07
sudo chown -R deploy:deploy !$
ls -ld !$
sudo -u deploy nano !$/config.env

ஒவ்வொரு வரியையும் இயக்குவதற்கு முன்பு, அந்த விரிவாக்கம் (expansion) உருவாக்கிய வரியை bash அச்சிடும்:

sudo chown -R deploy:deploy /srv/www/app/releases/2026-08-07

அந்த echo உங்கள் சரிபார்ப்பு ஆகும். கட்டளையின் வெளியீட்டைப் படிப்பதற்கு முன்பு இதைப் படியுங்கள், ஏனெனில் bash எதை !$ என்று முடிவு செய்தது என்பதைப் பார்க்க உங்களுக்குக் கிடைக்கும் ஒரே வாய்ப்பு இதுதான்.

இந்தச் சங்கிலி தொடர்கிறது, ஏனெனில் bash நீங்கள் தட்டச்சு செய்த !$-ஐ அல்ல, மாறாக விரிவாக்கம் செய்யப்பட்ட வரியையே history-ல் சேமிக்கிறது. எனவே, வரி 3 அதன் கடைசி argument-ஐ விரிவாக்கம் செய்யப்பட்ட வரி 2-லிருந்து எடுக்கிறது, வரி 4 வரி 3-லிருந்து எடுக்கிறது. வரி 4, ஒரு designator-ஐத் தொடர்ந்து உரை வரக்கூடும் என்பதையும் காட்டுகிறது: !$/config.env என்பது இறுதியில் /config.env சேர்க்கப்பட்ட பாதையாக மாறுகிறது, ஏனெனில் word designator /-ல் நின்றுவிடுகிறது.

அதே session-லிருந்து மேலும் ஒன்று. கோப்பைத் திருத்திய பிறகு, அதைக் கொண்டுள்ள directory-ஐ நீங்கள் பட்டியலிட விரும்புகிறீர்கள்:

ls -l !$:h

:h என்பது head modifier ஆகும். இது ஒரு பாதையிலிருந்து கடைசிப் பகுதியை நீக்குகிறது, dirname செய்யும் அதே வேலையை இது செய்கிறது. :t கடைசிப் பகுதியை மட்டும் வைத்திருக்கும், :r extension-ஐ நீக்கும், மற்றும் :e extension-ஐ மட்டும் வைத்திருக்கும்.

!! மற்றும் sudo !! மூலம் முந்தைய கட்டளையை மீண்டும் இயக்குதல்

நீங்கள் sudo-ஐ மறக்கும்போது, service manager அதைத் தெரிவிக்கும்:

systemctl restart nginx
Failed to restart nginx.service: Interactive authentication required.
sudo !!

Bash, !!-ஐ முந்தைய வரியின் உரையைக் கொண்டு மாற்றும், எனவே shell sudo systemctl restart nginx-ஐ இயக்கும்.

!! என்பது சரியாக முந்தைய வரியாகும், அது எதுவாக இருந்தாலும் சரி. இங்கேயேதான் வழக்கமான தவறு நடக்கிறது. தோல்வியடைந்த கட்டளைதான் கடைசியாக இயக்கியது என்று நீங்கள் நம்புவீர்கள், ஆனால் அதற்குள் நீங்கள் ஒரு cd அல்லது history-ஐ இயக்கியிருக்கலாம், அல்லது தோல்வியடைந்த கட்டளை இரண்டு வரிகளுக்கு முன்னால் இருந்திருக்கலாம். sudo !! அப்போது தவறான கட்டளையை root உரிமைகளுடன் இயக்கிவிடும். உங்களுக்கு உறுதியாகத் தெரியவில்லை என்றால், முதலில் அதை அச்சிடுங்கள்:

sudo !!:p

:p விரிவுபடுத்தப்பட்ட வரியை அச்சிடும், ஆனால் அதை இயக்காது. அச்சிடப்பட்ட வரி உங்கள் history-ல் சேர்க்கப்படும், எனவே அது சரியாக இருந்தால், அடுத்த வரியில் ஒரு சாதாரண !!-ஐ இடுவதன் மூலம் அதை இயக்கலாம்.

கடைசி argument-ஐ !$ மூலம் மீண்டும் பயன்படுத்துதல்

!$ என்பது முந்தைய வரியின் கடைசிச் சொல்லாகும். இதுவே நீங்கள் அடிக்கடி பயன்படுத்தும் வடிவமாகும், ஏனெனில் நீங்கள் கையாளும் கோப்புப் பாதை (path) அல்லது service பெயர் பொதுவாக கடைசிச் சொல்லாகவே இருக்கும்.

sudo systemctl status nginx
sudo systemctl reload !$

இதில் இரண்டு விஷயங்கள் பயனர்களை ஆச்சரியப்படுத்தும்.

முதலாவதாக, !$ என்பது நீங்கள் நினைக்கும் கடைசி argument அல்ல, அது கடைசி சொல் மட்டுமே. முந்தைய வரி ஒரு redirection-ல் முடிந்தால், கடைசிச் சொல் அந்த redirect இலக்காகவே இருக்கும்:

sudo nginx -T > /tmp/nginx-dump.conf
less !$

இது சரியாக வேலை செய்யும். ஆனால் journalctl -u nginx > /tmp/log.txt-க்கு பிறகு, !$ என்பது /tmp/log.txt ஆகும், nginx அல்ல. திரையில் தோன்றும் வரியை கவனமாகப் பார்க்கவும்.

இரண்டாவதாக, இந்த விரிவாக்கம் (expansion) உரை சார்ந்தது, எனவே ஒரு variable விரிவாக்கப்படாமல் அப்படியே திரும்ப வரும். ls $HOME/backups-க்கு பிறகு, !$ என்பது உங்களுக்கு $HOME/backups என்ற எழுத்துக்களைத் தரும், அதை bash மீண்டும் ஒரு சாதாரண parameter-ஆக விரிவாக்கும். இந்த வரிசையை நினைவில் கொள்க: history expansion என்பது parameter expansion மற்றும் $( ) மூலம் command substitution ஆகியவற்றுக்கு முன்பே இயங்கும். எனவே, இது மதிப்புகளைப் பார்க்காது, உரையை மட்டுமே பார்க்கும்.

இதனுடன் தொடர்புடைய பிற வடிவங்களையும் தெரிந்து கொள்வது பயனுள்ளது. !^ என்பது முதல் argument, !:2 என்பது இரண்டாவது, மற்றும் !:2-4 என்பது ஒரு வரம்பைக் (range) குறிக்கும். !!:$ என்பது !$-ஐ எழுதுவதற்கான நீண்ட முறையாகும்.

நீங்கள் கட்டளையை இயக்குவதற்கு முன் உரையைச் சரிபார்க்க விரும்பினால், Alt-. (அல்லது Esc மற்றும் பின் .) அழுத்தவும். Readline முந்தைய கட்டளையின் கடைசி argument-ஐ நேரடியாக உங்கள் prompt-ல் செருகும், அங்கு நீங்கள் அதைத் திருத்தலாம். மீண்டும் அழுத்தினால், அதற்கு முந்தைய கட்டளையின் கடைசி argument-க்குச் செல்லும். நீங்கள் Enter அழுத்தும் வரை எதுவும் இயங்காது.

!* மூலம் அனைத்து ஆர்குமெண்ட்களையும் கடத்துதல்

!* என்பது முதல் சொல்லைத் தவிர முந்தைய வரியின் மற்ற அனைத்துச் சொற்களையும் குறிக்கும்.

stat /srv/www/app/shared/config.env /srv/www/app/shared/secrets.env
sudo chmod 600 !*

"முதல் சொல்லைத் தவிர" என்ற சொற்றொடர் இங்கு முக்கியப் பங்கு வகிக்கிறது. !* என்பது 0-வது சொல்லை மட்டும் நீக்கும், எனவே ஆப்ஷன்கள் (options) பாதைகளுடன் (paths) சேர்ந்து செல்லும். ls -l file1 file2-க்கு பிறகு, !* என்பது -l file1 file2 ஆகிறது, எனவே sudo chmod 600 !* தோல்வியடைகிறது, ஏனெனில் chmod ஆனது -l-ஐ ஒரு ஆர்குமெண்டாகப் பெறுகிறது. சொற்களை பூஜ்ஜியத்திலிருந்து எண்ணி ஒரு பகுதியை மட்டும் எடுக்கவும்: !!:2* என்பது 2-வது சொல்லிலிருந்து இறுதி வரை உள்ளவற்றைக் குறிக்கும்.

sudo-ஐப் பயன்படுத்தும்போதும் இதே சிக்கல் ஏற்படுகிறது. sudo chown deploy:deploy /srv/www/app-க்கு பிறகு, 0-வது சொல் sudo மற்றும் 1-வது சொல் chown ஆகும், எனவே !* அடுத்த கட்டளையான chown deploy:deploy /srv/www/app-க்கு அவற்றை வழங்குகிறது. இது நீங்கள் பெரும்பாலும் விரும்பாத ஒன்றாகவே இருக்கும்.

!n மற்றும் !-n மூலம் ஒரு கட்டளையை அதன் இடத்தைக் கொண்டு தேர்ந்தெடுத்தல்

history ஒவ்வொரு உள்ளீட்டிற்கு முன்பும் ஒரு எண்ணுடன் பட்டியலை அச்சிடுகிறது.

history 5
  512  sudo nginx -t
  513  sudo systemctl reload nginx
  514  ss -tulpn
  515  sudo tail -f /var/log/nginx/error.log
  516  history 5

!513 513-வது உள்ளீட்டை மீண்டும் இயக்குகிறது. !-2 நீங்கள் தற்போது தட்டச்சு செய்யும் வரியிலிருந்து இரண்டு வரிகளுக்கு முந்தைய உள்ளீட்டை இயக்குகிறது, எனவே !-1 மற்றும் !! ஆகிய இரண்டும் ஒரே பொருளைக் குறிக்கின்றன.

எண்களைப் பயன்படுத்துவதற்கு முன்பு அவற்றைச் சரிபார்க்கவும். நீங்கள் எதை இயக்கினாலும் !-2 ஒவ்வொரு முறையும் புதிய இடத்தைக் குறிக்கும், நீங்கள் கவனக்குறைவாக இயக்கும் ls-ம் இதில் அடங்கும். ஒரு session-க்குள் முழுமையான எண்கள் (absolute numbers) மாறாமல் இருக்கும், ஆனால் அதே server-ல் மற்றொரு session-ல் அவை அதே எண்களாக இருக்காது, மேலும் உங்கள் அடுத்த login-க்குப் பிறகு history file மீண்டும் வாசிக்கப்பட்ட பிறகும் அவை மாறக்கூடும். நேற்று நீங்கள் நினைவில் வைத்திருந்த எண், இன்று வேறொரு கட்டளையைக் குறிக்கலாம்.

!string முன்னொட்டைப் பயன்படுத்தி ஒரு கட்டளையை மீண்டும் இயக்குதல்

!string, string-ல் தொடங்கும் மிக அண்மைய கட்டளையை இயக்குகிறது.

!ss

இது மேலே உள்ள பட்டியலில் இருந்து ss -tulpn-ஐ மீண்டும் இயக்குகிறது, இது Linux server-ல் எந்தெந்த ports திறந்திருக்கின்றன என்பதில் விவரிக்கப்பட்டுள்ள listening socket சரிபார்ப்பு ஆகும். !?string? கட்டளையின் தொடக்கத்தில் மட்டுமல்லாமல் வரியின் எந்தப் பகுதியிலும் பொருந்துவதைத் தேடும், இது கட்டளையின் பெயர் நினைவில் இல்லை ஆனால் ஒரு argument நினைவில் இருக்கும்போது பயனுள்ளதாக இருக்கும்.

முன்னொட்டை நீளமாக வைத்திருங்கள். !s என்பது ss, sudo, systemctl அல்லது shutdown ஆகியவற்றில் எது மிக அண்மையில் இயங்கியதோ அதனுடன் பொருந்தும், அது இயங்கும் வரை எது என்று உங்களுக்குத் தெரியாது. !string:p கட்டளையை இயக்காமல் அது எதனுடன் பொருந்துகிறது என்பதை மட்டும் அச்சிடும். எதுவும் பொருந்தவில்லை என்றால், bash bash: !ss: event not found என்று அச்சிட்டு எதையும் இயக்காது, இது பாதுகாப்பான முடிவாகும்.

^old^new மூலம் ஒரு எழுத்துப் பிழையைச் சரிசெய்தல்

sudo systemctl status ngnix
Unit ngnix.service could not be found.
^ngnix^nginx

முந்தைய வரியில் உள்ள முதல் ngnix-ஐ nginx கொண்டு மாற்றி, அந்த வரியை shell மீண்டும் இயக்கும். முதல் பொருத்தம் (match) மட்டுமே மாற்றப்படும். அனைத்து பொருத்தங்களையும் மாற்ற, !!:gs/ngnix/nginx/ என்ற நீண்ட வடிவத்தைப் பயன்படுத்தவும். இதில் s என்பது பிரதியீடு (substitute) என்பதையும், g என்பது முழு வரியிலும் மாற்றத்தைச் செய்ய வேண்டும் என்பதையும் குறிக்கும்.

இயக்குவதற்கு முன் விரிவாக்கத்தை (expansion) அச்சிடுதல்

ஒரு விரிவாக்கம் நீங்கள் எதிர்பாராத ஒன்றை இயக்கும் விபத்தைத் தடுக்கும் இரண்டு பழக்கங்கள் உள்ளன.

முதலாவது :p ஆகும், இதை நீங்கள் ஏற்கனவே பார்த்திருப்பீர்கள். ஒரு விரிவாக்கத்தின் இறுதியில் இதைச் சேர்த்தால், Bash அதை இயக்குவதற்குப் பதிலாக அதன் முடிவை அச்சிடும்: !!:p, அல்லது !systemctl:p. அச்சிடப்பட்ட வரி உங்கள் history-ல் சேரும், எனவே அதன் பிறகு !!-ஐப் பயன்படுத்தினால் நீங்கள் இப்போது பார்த்த கட்டளையை இயக்கலாம்.

இரண்டாவது முறை மிகவும் வலிமையானது, ஏனெனில் இது எதையும் நினைவில் கொள்ளாமலேயே ஒவ்வொரு விரிவாக்கத்திற்கும் பொருந்தும்:

shopt -s histverify

இந்த வரியை ~/.bashrc-ல் சேர்க்கவும். histverify அமைக்கப்பட்டிருக்கும்போது, நீங்கள் Enter அழுத்தினால் விரிவாக்கம் இயங்காது. Bash விரிவாக்கப்பட்ட வரியை மீண்டும் உங்கள் prompt-ல் எழுதும், எனவே நீங்கள் அதை வாசித்துத் திருத்தலாம்; இரண்டாவது முறையாக Enter அழுத்தினால் மட்டுமே அது இயங்கும். இதற்கு ஒரு கூடுதல் keystroke தேவைப்படும், ஆனால் இது அனைத்து வகையான விபத்துகளையும் தவிர்க்கிறது. இதற்கு readline தேவை, எனவே இது interactive prompt-ல் மட்டுமே செயல்படும்.

Ctrl-R என்பது வேலை செய்வதற்கான மற்றொரு வழியாகும், இது எதையும் விரிவாக்கம் செய்யாது. Ctrl-R அழுத்தி ஒரு கட்டளையின் பகுதியைத் தட்டச்சு செய்யவும். Prompt ஒரு reverse-i-search prompt-ஆக மாறி, நீங்கள் தட்டச்சு செய்யும்போதே மிக சமீபத்திய பொருத்தத்தைக் காட்டும். பழைய பொருத்தங்களுக்குச் செல்ல மீண்டும் Ctrl-R அழுத்தவும். Enter அழுத்தினால் காட்டப்படும் வரி இயங்கும். Ctrl-G தேடலை ரத்து செய்து உங்கள் அசல் prompt-ஐத் தரும். இடது arrow key தேடலை முடித்து, திருத்துவதற்காகப் பொருத்தப்பட்ட வரியை உங்கள் prompt-ல் அப்படியே வைத்திருக்கும்.

கட்டளையை முதலில் பார்க்க விரும்பும்போது Ctrl-R-ஐப் பயன்படுத்தவும். கட்டளை ஒரு வரிக்கு முந்தையது மற்றும் அதைத் திரையில் இன்னும் வாசிக்க முடியும் என்றால் !! மற்றும் !$-ஐப் பயன்படுத்தவும்.

echo "done!" கட்டளை ஏன் event not found என்று காட்டுகிறது

echo "deploy done!"
bash: !": event not found

Quoting முறை முடிவடைவதற்கு முன்பே history expansion செயல்படுகிறது, மேலும் double quotes-ஆல் ! குறியீட்டைப் பாதுகாக்க முடியாது. Single quotes மற்றும் backslash மட்டுமே இதைச் செய்யும். எனவே echo 'deploy done!' நீங்கள் எதிர்பார்ப்பதை அச்சிடும். Backslash-ம் இந்த expansion-ஐத் தடுக்கும், ஆனால் double quotes-க்குள் backslash-ஐ bash அப்படியே வெளியீட்டில் விட்டுவிடும், எனவே single quotes பயன்படுத்துவதே சரியான தீர்வாகும்.

கடவுச்சொற்களைப் (passwords) பயன்படுத்தும்போது இது பெரும் சிக்கலை ஏற்படுத்துகிறது, ஏனெனில் வலுவான கடவுச்சொற்களில் பெரும்பாலும் ! இருக்கும். mysql -u app -p"S3cret!pass" போன்ற ஒரு கட்டளை, event-not-found பிழையுடன் தோல்வியடையும், அல்லது ஏதேனும் history entry அதனுடன் ஒத்துப்போனால், தவறான string-ஐ அமைதியாக அனுப்பிவிடும். Single quotes-ஐப் பயன்படுத்துங்கள், அல்லது இன்னும் சிறப்பாக, அந்த கருவியே உங்களிடம் கடவுச்சொல்லைக் கேட்கும்படி செய்யுங்கள், அப்போதுதான் ரகசியத் தகவல் command line-க்கு வராது. இந்த பழக்கம் உங்கள் account பாதுகாப்பின் ஒரு பகுதியாகும்: keys மற்றும் கடவுச்சொற்களை ஒரு புதிய server-ல் எவ்வாறு கையாள்வது என்பதை அறிய புதிய VPS-ல் முதல் பத்து நிமிடங்கள் என்பதைப் பார்க்கவும்.

நீங்கள் ! குறியீடுகள் நிறைந்த ஒரு உரையை paste செய்யப் போகிறீர்கள் என்றால், அந்த session-க்கு மட்டும் set +H மூலம் expansion-ஐ நிறுத்திவிட்டு, மீண்டும் set -H மூலம் அதைச் செயல்படுத்தவும்.

HISTSIZE, HISTFILESIZE and where your history is kept

Two variables, and people mix them up because the names are close.

  • HISTSIZE is how many commands the running shell keeps in memory.
  • HISTFILESIZE is how many lines are kept in the file on disk, ~/.bash_history unless HISTFILE says otherwise.

The file is written when the shell exits, and it is truncated to HISTFILESIZE lines at that moment. Ubuntu's default ~/.bashrc sets 1000 and 2000. Check what yours actually holds:

grep HIST ~/.bashrc
echo "$HISTSIZE $HISTFILESIZE $HISTFILE"

Raise both if your !string searches keep missing commands you know you ran. Values of 10000 and 20000 are common and cost almost nothing, because the file is plain text. A negative value means no limit at all.

Timestamps help when you come back to a server after a week away:

export HISTTIMEFORMAT='%F %T '

history then prints a date and time in front of each entry, because bash starts writing a comment line holding the epoch seconds before each command in the file.

The common complaint is that history goes missing when you use more than one terminal. Each shell keeps its own list in memory and writes it out at exit, so without histappend the last shell to close overwrites what the others saved. Two settings fix it:

shopt -s histappend
export PROMPT_COMMAND='history -a'

histappend makes the shell add its list to the end of the file instead of replacing the file. history -a appends new lines after every prompt, so a session that is killed rather than closed cleanly still leaves its commands behind. Ubuntu's default ~/.bashrc sets histappend already. This matters more the more machines you run, because history is stored per user per machine, so when you are managing several servers from one workstation the !$ you want may simply be on another host.

Bash history-ல் ரகசியங்களைச் சேமிக்காமல் தவிர்த்தல்

HISTCONTROL எந்தெந்த வரிகள் சேமிக்கப்பட வேண்டும் என்பதைத் தீர்மானிக்கிறது.

  • ignorespace இடைவெளியுடன் (space) தொடங்கும் எந்த வரியையும் சேமிக்காது.
  • ignoredups அதற்கு முந்தைய வரியைப் போலவே இருக்கும் வரியைச் சேமிக்காது.
  • ignoreboth மேற்கூறிய இரண்டையும் செய்யும்.
  • erasedups சேமிக்கப்படும் வரியின் பழைய நகல்கள் அனைத்தையும் நீக்கிவிடும்.
export HISTCONTROL=ignoreboth

ignorespace செயல்பாட்டில் இருக்கும்போது, ஒரு கட்டளைக்கு முன்னால் ஒரு இடைவெளி இட்டால், அது in-memory பட்டியலில் சேராது; எனவே அது கோப்பிலும் (file) சேமிக்கப்படாது. இதை நம்புவதற்கு முன் echo "$HISTCONTROL" மூலம் அதன் மதிப்பைச் சரிபார்க்கவும். Ubuntu-வின் default user .bashrc, ignoreboth-ஐ அமைக்கிறது. ஆனால் root shell அல்லது minimal image-ல் இது அமைக்கப்படாமல் இருக்கலாம்; அவ்வாறு இருந்தால், முன்னால் இடப்படும் இடைவெளி எந்தப் பயனும் தராது, அந்த வரியும் மற்ற வரிகளைப் போலவே சேமிக்கப்படும்.

இது எதைப் பாதுகாக்கிறது என்பதில் தெளிவாக இருக்கவும். அந்த வரி ~/.bash_history-ல் சேமிக்கப்படாது. ஆனால் process இயங்கும்போது ps வெளியீட்டில் அது தெரியும்; எனவே அந்த server-ல் உள்ள எந்தவொரு பயனரும் அதைப் பார்க்க முடியும். sudo தான் இயக்கிய கட்டளையை system log-ல் பதிவு செய்யும். History கோப்பு plain text வடிவில் இருப்பதால், அதை mode 600-ல் வைத்திருக்கவும். உங்கள் home directory-ஐ அணுகக்கூடிய எவரும் உங்கள் கடைசி சில ஆயிரம் கட்டளைகளைப் படிக்க முடியும் என்பதை நினைவில் கொள்க.

ஏற்கனவே ஏதேனும் ரகசியத் தகவல் பட்டியலில் இருந்தால், அந்தப் பதிவை நீக்கிவிட்டு கோப்பை மீண்டும் எழுதவும்:

history
history -d 517
history -w

history -d அந்தப் பதிவை நினைவகத்திலிருந்து நீக்குகிறது, history -w தற்போதைய பட்டியலை கோப்பின் மீது மீண்டும் எழுதுகிறது. history -c முழுப் பட்டியலையும் அழித்துவிடும். HISTIGNORE என்பது ரகசியங்களுக்காக அல்லாமல், தேவையற்ற தகவல்களைத் தவிர்க்க உதவும் அமைப்பாகும்: HISTIGNORE='ls:pwd:history:clear' அந்த வரிகளைப் பட்டியலில் சேராமல் தடுக்கும், இதனால் உங்கள் தேடல்கள் பயனுள்ள முடிவுகளைத் தரும்.

Shell script-ல் history expansion ஏன் செயல்படுவதில்லை

History expansion என்பது interactive shell-களுக்கு உரியது. ஒரு script non-interactive shell-ல் இயங்குகிறது; அங்கு history list கிடையாது மற்றும் expansion வசதி முடக்கப்பட்டிருக்கும். எனவே, !! மற்றும் !$ ஆகியவை சாதாரண உரையாகவே கருதப்படும். ஒரு script-க்குள் sudo !! என்று கொடுத்தால், அது !! என்ற பெயரில் உள்ள ஒரு கட்டளையை இயக்க sudo-விடம் கேட்கும், இது தோல்வியில் முடியும்.

நீங்கள் தற்போது பயன்படுத்தும் shell-ன் அமைப்பைச் சரிபார்க்கவும்:

echo $-

இதன் வெளியீடு தற்போதைய option flags-ஐக் காட்டும், இது himBHs போன்ற வடிவில் இருக்கும். i என்பது shell interactive நிலையில் இருப்பதையும், H என்பது history expansion செயல்பாட்டில் இருப்பதையும் குறிக்கும். இதே வரியை ஒரு script-க்குள் இயக்கினால், இந்த எழுத்துக்கள் அங்கு இருக்காது.

இதுவே உங்கள் shell செயல்பாட்டின் இரண்டு பகுதிகளுக்கும் இடையிலான வேறுபாடு. Command prompt-ல், !$ மற்றும் Ctrl-R ஆகியவை நீங்கள் ஏற்கனவே பார்த்த கட்டளைகளை மீண்டும் தட்டச்சு செய்யும் நேரத்தைக் குறைக்கும். ஒரு கோப்பில் (file), நீங்கள் பெயர்களைப் பயன்படுத்த வேண்டும்: path-ஐ ஒரு variable-ல் சேமிக்கவும் அல்லது command substitution மூலம் வெளியீட்டைப் பெறவும். உங்கள் தனிப்பட்ட history-ஐச் சார்ந்திருக்கும் ஒரு script, அதை இயக்கும் அடுத்த நபருக்கு வேறுவிதமாகச் செயல்படும்; இது script-ன் நோக்கத்திற்கே எதிரானது.

இந்த காரணத்தினால், இந்தப் பக்கத்தில் உள்ள ஒவ்வொரு உதாரணமும் ஒரு live prompt-ல் தட்டச்சு செய்யப்பட வேண்டியவை. இவை எதையுமே ஒரு .sh கோப்பில் நகலெடுத்து (paste) இயக்கினால் அதே முடிவைத் தராது.

FAQ

bash-ல் !! எதைக் குறிக்கிறது?

!! என்பது முந்தைய கட்டளை வரியின் முழு உரையையும் விரிவுபடுத்தும். எனவே, sudo !! என்பது உங்கள் கடைசி கட்டளையை root பயனர் உரிமையுடன் மீண்டும் இயக்கும். இந்த விரிவுபடுத்தல் உரை அடிப்படையிலானது மற்றும் bash வரியைப் பகுப்பாய்வு செய்வதற்கு முன்பே நடக்கும். கட்டளையை இயக்குவதற்கு முன், bash அந்த முழு வரியையும் திரையில் காட்டும். முந்தைய வரி என்னவென்று உங்களுக்குத் தெரியவில்லை என்றால், முதலில் sudo !!:p என்று தட்டச்சு செய்யவும். :p கட்டளையை இயக்காமல் அதன் விரிவுபடுத்தலை மட்டும் காட்டும். மேலும், இது அந்த வரியை உங்கள் history-ல் சேர்க்கும், எனவே அடுத்து வரும் !! அதை இயக்கும்.

முந்தைய கட்டளையின் கடைசி argument-ஐ எவ்வாறு மீண்டும் பயன்படுத்துவது?

!$-ஐப் பயன்படுத்தவும். sudo mkdir -p /srv/www/app/releases-க்கு பிறகு, ls -ld !$ என்ற வரி ls -ld /srv/www/app/releases என மாறும். இது வரியின் கடைசி சொல்லை (word) எடுத்துக்கொள்ளும், எனவே வரியின் இறுதியில் உள்ள redirection இலக்கும் கடைசி சொல்லாகவே கருதப்படும். இதனுடன் நீங்கள் கூடுதல் உரையையும் சேர்க்கலாம்: !$/config.env என்பது பாதையுடன் உரையைச் சேர்க்கும், ஏனெனில் word designator /-ல் நின்றுவிடும். இதற்கு மாற்றாக, interactive முறையில் Alt-.-ஐப் பயன்படுத்தலாம்; இது அதே உரையை உங்கள் prompt-ல் செருகும், எனவே Enter அழுத்துவதற்கு முன் நீங்கள் அதைச் சரிபார்க்கலாம்.

எனது உரையில் ஆச்சரியக்குறி (exclamation mark) இருக்கும்போது ஏன் bash "event not found" என்று காட்டுகிறது?

Double quotes, !-ஐ history expansion-லிருந்து பாதுகாக்காது. எனவே, echo "done!" என்று எழுதினால், bash ஒரு history event-ஐத் தேடி bash: !": event not found என்று பிழையைக் காட்டும். Single quotes இதைப் பாதுகாக்கும், எனவே echo 'done!' என்று எழுதவும். Backslash-ம் இந்த விரிவுபடுத்தலைத் தடுக்கும், ஆனால் double quotes-க்குள் இருக்கும்போது bash அந்த backslash-ஐ வெளியீட்டிலேயே விட்டுவிடும். ! கொண்ட நீண்ட உரையை paste செய்ய, set +H மூலம் அந்த session-க்கான expansion-ஐ முடக்கவும்.

எனது shell script-ல் ஏன் !! மற்றும் !$ வேலை செய்யவில்லை?

History expansion என்பது interactive shells-ல் மட்டுமே செயல்படும். ஒரு script non-interactive முறையில் இயங்குவதால், shell ஒரு history பட்டியலை உருவாக்காது. எனவே, !! என்பது சாதாரண உரையாகவே வரியிலேயே தங்கிவிடும். நீங்கள் எந்த நிலையில் இருக்கிறீர்கள் என்பதை அறிய echo $--ஐ இயக்கவும்: ஒரு interactive shell, i மற்றும் H உள்ளிட்ட flags-ஐக் காட்டும், ஆனால் script எதையும் காட்டாது. Scripts-ல், இதற்குப் பதிலாக variable அல்லது command substitution-ஐப் பயன்படுத்தவும்.

எனது bash history-ல் கடவுச்சொல் (password) சேமிக்கப்படாமல் தடுப்பது எப்படி?

~/.bashrc கோப்பில் HISTCONTROL=ignorespace அல்லது HISTCONTROL=ignoreboth-ஐ அமைக்கவும். அதன் பிறகு, கட்டளையைத் தொடங்கும் முன் ஒரு space-ஐச் சேர்த்தால், அந்தக் கட்டளை history-ல் சேமிக்கப்படாது. முதலில் echo "$HISTCONTROL" மூலம் அதன் மதிப்பை உறுதிப்படுத்தவும், ஏனெனில் அது unset நிலையில் இருந்தால், தொடக்கத்தில் உள்ள space எந்த மாற்றத்தையும் ஏற்படுத்தாது. இது அந்த வரியை ~/.bash_history-ல் சேமிக்கப்படாமல் மட்டுமே தடுக்கும். கட்டளை இயங்கும்போது ps-ல் அது தெரியும், மேலும் sudo அது இயக்கியதை log செய்யும். ஒரு ரகசியத் தகவல் ஏற்கனவே சேமிக்கப்பட்டிருந்தால், history மூலம் அதன் எண்ணைக் கண்டறிந்து, பின் history -d <number> மற்றும் அதைத் தொடர்ந்து history -w-ஐ இயக்கி கோப்பைத் திருத்தவும்.