nano dosya kaydetmiyor: permission denied hatası çözümü
nano editorde dosya kaydederken alinan permission denied hatasinin dort temel sebebi ve cozumu. Dosya sahibi, dizin izinleri, salt okunur disk veya UID sorunlarini inceleyin.
Neden nano dosyanızı kaydetmiyor
nano dosyanızı dört nedenden dolayı kaydedemez: dosyanın sahibi siz değilsinizdir, üst dizin nano'nun yapmaya çalıştığı işleme izin vermiyordur, dosya sistemi salt okunurdur veya disk alanı dolmuştur ya da farklı bir kullanıcı kimliği (UID) ile çalışan bir container içindesinizdir. İlk iki neden izin sorunlarıdır, son ikisi ise değildir. Bu sorunları belirtilen sırayla kontrol edin; çünkü ilk neden çoğu durumu kapsar, doğrulanması tek bir komut gerektirir ve çözümü sudo nano yerine sudoedit kullanmaktır.
Düzenleyici açık olduğu sürece hiçbir veri kaybolmaz. Metniniz bellekte tutulur; bu nedenle dosyayı açık bırakabilir, arabelleği (buffer) sahibi olduğunuz bir yola yazabilir ve ardından dosyayı yerine taşıyabilirsiniz. Bu kurtarma yöntemi, kılavuzun sonuna yakın bir bölümde açıklanmıştır.
İzinleri değiştirmeden önce bu kontrolleri çalıştırın
Her komutu düzenlemekte olduğunuz gerçek yola yönlendirin. Bu komutlar farklı sorulara yanıt verir, bu nedenle herhangi bir değişiklik yapmadan önce hepsini çalıştırın. Hangi kontrolün başarısız olduğunu bilmeden izinleri değiştirmek, genellikle mevcut sorunun üzerine ikinci bir sorun eklenmesine neden olur.
id
ls -l /etc/nginx/nginx.conf
ls -ld /etc/nginx
namei -l /etc/nginx/nginx.conf
findmnt -no SOURCE,FSTYPE,OPTIONS -T /etc/nginx/nginx.conf
df -h /etc/nginx
df -i /etc/nginxid şu an sahip olduğunuz kullanıcı kimliğini ve grup kimliklerini yazdırır. ls -l dosyanın sahibini, grubunu ve izin bitlerini gösterir. ls -ld aynı bilgileri dosyayı barındıran dizin için gösterir; bu ayrı bir sorudur ve ayrı bir yanıtı vardır. namei -l yolun her bir parçasını tarar ve her parçanın sahibini ve izinlerini listeler, böylece her iki soruyu da tek bir çıktıda yanıtlar. findmnt ilgili yolun altındaki dosya sistemini ve bağlama (mount) seçeneklerini belirtir. df -h boş alanı, df -i ise alandan bağımsız olarak tükenen boş inode sayısını raporlar. Eğer bu izin dizeleri henüz tanıdık değilse, ls -l çıktısındaki izin dizesi nasıl okunur konusuna göz atarak başlayın.
Neden 1: Dosya root kullanıcısına ait ve siz değilsiniz
Okuma ve yazma izinleri birbirinden ayrıdır ve /etc altındaki çoğu dosya herkes tarafından okunabilir. nano uygulamasının dosyayı açıp içeriği göstermesi ve serbestçe yazmanıza izin vermesinin nedeni budur: bunların hiçbiri diske yazma işlemi gerçekleştirmez. Reddetme işlemi, çekirdeğin kullanıcı kimliğinizi ve grup kimliklerinizi dosyanın sahibi, grubu ve diğer bitleri ile karşılaştırdığı kaydetme aşamasında gerçekleşir. nano, çekirdekten gelen yanıtı iletmektedir; bu nedenle hiçbir nano seçeneği sonucu değiştirmez.
id ve ls -l birlikte bu durumu belirler. Dosyanın sahibi root kullanıcısıdır, siz root değilsiniz ve diğer bitleri yazma izni vermemektedir. Ctrl-O tuşlarına tekrar basmak sorunu çözmeyecektir.
root sahipliğindeki bir dosyayı düzenlemek için neden sudoedit doğru yoldur
SUDO_EDITOR=nano sudoedit /etc/nginx/nginx.confsudo, dosyanın sahibi siz olacak şekilde geçici bir kopyasını oluşturur, nano uygulamasını bu kopya üzerinde kendi kullanıcınızla çalıştırır ve düzenleyici kapandığında sonucu root yetkileriyle orijinal yerine kopyalar. Düzenleyici hiçbir zaman root olarak çalışmaz. sudo -e, farklı bir isim altındaki aynı komuttur. Düzenleyici sırasıyla SUDO_EDITOR, ardından VISUAL ve son olarak EDITOR içerisinden seçilir; bu nedenle shell profilinizdeki export EDITOR=nano ayarı, bunu her yerde varsayılan hale getirir. Eğer sudoers dosyanızda env_editor bayrağı kapalıysa, bu değişkenler göz ardı edilir ve düzenleyici bunun yerine sudoers içindeki editor ayarından seçilir.
sudo nano de dosyayı kaydeder ve sorun tam olarak budur. Bu yöntem, oturum açık kaldığı sürece tam yetkili bir etkileşimli düzenleyiciye tüm dosya sistemi üzerinde root hakları tanır; dolayısıyla kaydetme isteminde yanlış yazılan bir yol, metninizin root yetkisiyle farklı bir sistem dosyasının üzerine yazılmasına neden olabilir. Sadece gerekli adımlar için sudo kullanan sıradan bir kullanıcı olarak çalışmak, edinilmesi gereken bir alışkanlıktır ve sudoedit, bir yapılandırma dosyasını düzenlediğiniz anda bu alışkanlığın nasıl göründüğünü temsil eder.
İki sudoedit kuralı insanları şaşırtır. Sembolik bir bağlantıyı düzenlemeyi reddeder ve root olmadığınız sürece, yazma izninizin olduğu bir dizin içindeki dosyayı düzenlemeyi reddeder. İkinci kuralın var olma nedeni, dizine yazma izni olan herhangi birinin düzenleyici açıkken dosyayı değiştirebilmesidir. Her iki davranış da sudoers varsayılanlarıdır (sudoedit_follow kapalı, sudoedit_checkdir açık). Henüz mevcut olmayan bir dosya sizin için oluşturulur.
Neden 2: üst dizinin gerçekte neyi kontrol ettiği
Diğer editörler için yazılan tavsiyeler, bir kaydetme işleminin dizin üzerinde yazma izni gerektirdiğini belirtir; çünkü birçok editör, dosyayı yeni bir dosya olarak yazıp eskisinin üzerine yeniden adlandırarak kaydeder. nano bu şekilde çalışmaz. Belirttiğiniz dosyayı açar ve doğrudan o dosyanın içine yazar; bu nedenle halihazırda var olan bir dosya için dizinin yazma biti hiçbir zaman sorgulanmaz.
Dizin yine de diğer hususları belirler, bu yüzden ls -ld kontrol listesindedir:
- Henüz var olmayan bir dosya oluşturmak, dizin üzerinde yazma ve çalıştırma izni gerektirir; çünkü dizine yeni bir isim eklenmesi gerekir. Yeni dosyanın hangi izinlerle başlayacağına umask karar verir.
- Dosyaya ulaşabilmek için, yol üzerindeki her dizinde çalıştırma izni (arama izni olarak da bilinir) gerekir. Bu izne sahip olmayan tek bir dizin, altındaki her şeyi engeller ve
namei -lsize hangisinin sorunlu olduğunu gösterir. - Yedeklemelerle veya dosya kilitleme açıkken kaydetme yapmak, orijinalin yanında ikinci bir dosya oluşturur; bu nedenle bu özellikler yazılabilir bir dizin gerektirir. Yedeklemeler
-Bseçeneği veya bir nanorc içindekiset backupile yapılır; kilitleme ise-Gveyaset lockingile ilgilidir. Siz veya dağıtımınız etkinleştirmediği sürece her ikisi de kapalıdır.
Dizin izinleri sistemin diğer yerlerinde de aynı ağırlığa sahiptir. SSH sunucusu, ev dizininiz veya .ssh dizininiz diğer kullanıcılar tarafından yazılabilir olduğunda bir anahtarı reddeder; bu, SSH'in giriş sırasında anahtarınızı geri çevirmesinin yaygın bir nedenidir.
nano halihazırda orada bulunan dosyaya yazdığı için, dosya inode değerini korur; bu, isim arkasındaki disk üzerindeki kimliktir. Dosyayı açık tutan herhangi bir süreç onu takip etmeye devam eder ve bir container içine bind mount edilmiş tek bir dosya çalışmaya devam eder. Dosyayı değiştirerek kaydeden editörler bu mount işlemini bozar, çünkü mount işlemi isme değil inode değerine bağlıdır.
Neden 3: Dosya sistemi salt okunur durumda veya tamamen dolu
findmnt seçeneklerinde ro raporlanması, yazma işleminin hiçbir zaman başarılı olamayacağı anlamına gelir. Dosya sistemi ya /etc/fstab veya salt okunur bir bind mount aracılığıyla bu şekilde bağlanmıştır ya da çekirdek, bir disk hatasından sonra sistemi salt okunur olarak yeniden bağlamıştır. İkinci durum daha ciddidir. sudo dmesg -T | tail -50, yeniden bağlamaya yol açan giriş/çıkış ve dosya sistemi hatalarını gösterir; çözüm ise sistem bağlı değilken bir dosya sistemi denetimi yapmaktır. VPS ortamında bu, sağlayıcının kurtarma konsolu ile başlatma yapılması anlamına gelir.
Tamamen dolu bir dosya sistemi, aynı yazma işleminin farklı bir nedenle başarısız olmasına yol açar. df -h, olağan durumu kapsar. df -i ise genellikle gözden kaçan durumu açıklar: inode'lar, dosya sistemi oluşturulduğunda belirlenen sabit bir havuzdan gelir. Çok sayıda küçük dosyadan oluşan bir ağaç, df -h hala boş gigabaytlar gösterse bile tüm inode'ları tüketebilir. Disk alanı tükendiğinde ve görünürde hiçbir şey yer kaplamıyorsa, df ve du komutlarının dolu disk konusunda uyuşmazlığı başlığı, silinmiş ancak hala açık olan dosyaların neden olduğu bu sorunu açıklar.
Buradaki kafa karıştırıcı bir belirtiyi bir detay açıklar. ext4, dosya sistemi oluşturulduğunda bloklarının bir kısmını root kullanıcısı için ayırır; bu sayede normal kullanıcılar reddedildikten sonra bile root yazmaya devam edebilir. sudo bu durumda bir çözüm gibi görünse de disk tamamen dolar ve sorun daha kötü bir şekilde geri döner.
nano, yeni içeriği yazmadan önce dosyayı kısalttığı için, yazma işlemi sırasında alanın tükenmesi dosyanın eskisinden daha kısa kalmasına neden olabilir. Neredeyse dolu bir dosya sisteminde düzenleme yapmadan önce önemli yapılandırma dosyalarınızı kopyalayın. sudo cp -a /etc/nginx/nginx.conf /root/nginx.conf.bak, kopyalama sırasında dosya sahibi, grup ve izin bilgilerini korur.
Neden 4: bind mount düzenlediğiniz bir container içindesiniz
Dosya sahipliği sayısal değerlere dayanır. Çekirdek bir kullanıcı kimliği (UID) saklar; gördüğünüz isim ise aramayı yapan /etc/passwd aracına bağlıdır. Bu nedenle bir dosya, host üzerinde farklı bir isimle, container içinde ise farklı bir isimle veya sadece bir numara olarak görünebilir. İsimler yerine numaraları karşılaştırın: container içinde id -u komutunu, dosya üzerinde ise ls -ln komutunu çalıştırın.
Bind mount edilen bir dosya, host üzerindeki sahiplik bilgilerini korur. Host üzerindeki dosya sizin kullanıcınıza aitse ve container süreci farklı bir kullanıcı olarak çalışıyorsa, container içinde yazma işlemi reddedilir ve container içindeki sudo komutu host üzerindeki sahipliği değiştirmez. Sorunu host üzerinden, sahipliği container'ın çalıştığı kimliğe atayarak düzeltin veya container'ı dosyaların halihazırda sahibi olan kimlikle çalıştırın. linuxserver.io ve benzeri projelerden alınan imajlar, sürecin hangi kullanıcıyla çalışacağını belirleyen PUID ve PGID değişkenlerini kullanıma sunar.
Bilinmesi gereken iki container durumu daha vardır. :ro ile salt okunur (read-only) hale getirilen bir mount veya --read-only ile başlatılan bir container, sahiplik bilgisi ne olursa olsun yazma işlemlerini reddeder ve container içindeki cat /proc/mounts komutu bu bayrağı gösterir. Rootless Podman kullanımında, kullanıcı isim alanı (user namespace) container içindeki kullanıcı kimliklerini host üzerindeki bir kimlik aralığına eşler. Bu sayede container içinde root kullanıcısına ait görünen bir dosya, dışarıda sizin yetkisiz hesabınıza ait olur.
Bir de başarılı olup sonra kaybolan düzenlemeler vardır. Bir container içinde, mount olmayan bir yolda değiştirdiğiniz dosya, o container'ın yazılabilir katmanında yaşar ve container yeniden oluşturulduğunda bu katman silinir. Değişikliğin kalıcı olmasını istiyorsanız, dosyayı mount'un host tarafında veya imaj oluşturma aşamasında değiştirin.
Kaçış yolu: dosyayı sahip olduğunuz bir dizine kaydedin
Düzenleyici içerisinden yetki yükseltmeye çalışmayın. Ctrl-O tuşlarına basın, komut satırındaki yolu temizleyin, ev dizininiz altında /home/you/nginx.conf.new gibi bir yol yazın ve Enter tuşuna basın. Ardından çıkmak için Ctrl-X tuşlarını kullanın. Çalışmanız artık disktedir, size aittir ve geri kalanı sıradan bir dosya kopyalama işlemidir.
sudo cp /home/you/nginx.conf.new /etc/nginx/nginx.conf
sudo nginx -tBurada mv yerine cp kullanın. cp, mevcut dosyanın üzerine yazar; böylece dosya kendi sahibini, grubunu ve izinlerini korur. Aynı dosya sistemi üzerinde mv kullanmak, dosyayı sizin dosyanızla değiştirir; bu da /etc içinde kullanıcı hesabınıza ait bir yapılandırma dosyası bırakır ve bu durum çözmeniz gereken bir sonraki izin sorununa dönüşür.
Herhangi bir şeyi yeniden yüklemeden önce, dosyadan sorumlu araçla sonucu kontrol edin. sudo nginx -t, nginx yapılandırmasını ayrıştırır; sudo sshd -t ise SSH sunucu yapılandırmasını ayrıştırır. İki dosyanın, bu prosedürün tamamını sizin yerinize yapan özel düzenleyicileri vardır: /etc/sudoers için sudo visudo ve kendi cron işleriniz için crontab -e. Her biri geçici bir kopya üzerinde düzenleme yapar, sözdizimini kontrol eder ve dosyayı yalnızca ayrıştırma başarılı olursa kurar.
FAQ
Bir sistem dosyasını düzenlemek için sudo nano mu yoksa sudoedit mi kullanmalıyım?
sudoedit kullanın. Bu komut, dosyayı size ait geçici bir kopyaya dönüştürür, düzenleyiciyi kendi kullanıcınızla çalıştırır ve düzenleyiciden çıkıldığında sonucu root yetkileriyle geri yazar; böylece düzenleyicinin kendisi hiçbir zaman root ayrıcalıklarına sahip olmaz. nano kullanmak için SUDO_EDITOR, VISUAL veya EDITOR değişkenini nano olarak ayarlayın. sudo nano de çalışır ancak bu komut, etkileşimli bir düzenleyiciye oturum süresince sistemdeki her yola root erişimi sağlar; bu da kaydetme isteminde yanlış yazılan tek bir dosya adının sistem dosyasının zarar görmesine yol açabileceği anlamına gelir.
nano ile bir dosyayı kaydetmek için dizinde yazma iznine sahip olmam gerekir mi?
Zaten var olan bir dosya için gerekmez. nano doğrudan dosyanın içine yazar; bu nedenle çekirdek, dosya üzerindeki yazma bitini ve yol üzerindeki her dizinin çalıştırma bitini kontrol eder. Dizinin yazma biti, dosya henüz mevcut değilse (yeni bir isim oluşturulması gerektiğinden) veya yedekleme ya da dosya kilitleme özellikleri açıksa (her ikisi de orijinal dosyanın yanına ikinci bir dosya yazdığından) önem kazanır.
Dosya sahibi doğru görünüyor ve disk dolu değil. Yazma işlemini başka ne engelleyebilir?
Dört durum söz konusudur. Dosya sistemi salt okunur (read-only) olarak bağlanmış olabilir; bunu findmnt -no OPTIONS -T /etc/nginx/nginx.conf ile görebilirsiniz. Dosya, değiştirilemez (immutable) özniteliğine sahip olabilir; bunu lsattr ile görebilir, sudo chattr -i ile kaldırabilirsiniz; bu öznitelik ayarlı olduğunda root dahi dosyaya yazamaz. Boş alan olmasına rağmen inode havuzu tükenmiş olabilir; bunu df -i ile görebilirsiniz. SELinux veya AppArmor, izin bitleri izin verse dahi yazma işlemini reddedebilir; denetim günlüğü (audit log), denediğiniz yol üzerindeki bu reddi kaydeder.
Dosya hiçbir şekilde kaydedilemediğinde değişikliklerimi nereye koymalıyım?
Ctrl-O tuşlarına basın ve ev dizininiz altında veya kullanıcınızın yazma yetkisi olan başka bir yerde, sahip olduğunuz bir yol belirtin. Tampon bellek (buffer) hala hafızada olduğu için yazdığınız hiçbir şey kaybolmaz. Kaydedilen dosyayı daha sonra sudo cp ile yerine kopyalayın; bu komut orijinal dosyanın sahibini ve izinlerini korur. Ardından servisi yeniden yüklemeden önce servisin kendi test komutuyla dosyayı doğrulayın.
Docker container içindeki değişikliklerim neden kayboluyor?
Yol bir mount noktası değilse, yapılan değişiklik container'ın yazılabilir katmanına kaydedilir ve container değiştirildiğinde bu katman silinir. Dosyayı bir bind mount veya volume'un host tarafında düzenleyin ya da doğrudan imajın içine dahil edin. Yol bir bind mount olduğu halde kaydetme işlemi reddediliyorsa, container içindeki id -u çıktısını ls -ln komutundan gelen sayısal kullanıcı sahibi ile karşılaştırın: dosya host üzerindeki sahipliğini korur ve container sürecinin bu sahiplikle eşleşmesi gerekir.