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 yöntemdir
SUDO_EDITOR=nano sudoedit /etc/nginx/nginx.confsudo, dosyanın sahipliğini size ait olacak şekilde geçici bir kopyasını oluşturur, nano düzenleyicisini kendi kullanıcınızla bu kopya üzerinde çalıştırır ve düzenleyici kapandığında sonucu root yetkileriyle orijinal konumuna geri kopyalar. Düzenleyici hiçbir zaman root olarak çalışmaz. sudo -e, farklı bir isim altındaki aynı komuttur. Düzenleyici önce SUDO_EDITOR, ardından VISUAL ve son olarak EDITOR değişkenlerinden seçilir; bu nedenle shell profilinizdeki export EDITOR=nano ayarı, bunu her yerde varsayılan hale getirir. Eğer bu değişkenlerin hiçbiri mevcut ve çalıştırılabilir bir düzenleyiciyi işaret etmiyorsa, sudoedit varsayılan olarak vi olan sudoers içindeki editor ayarına geri döner.
sudo nano de dosyayı kaydeder ve sorun tam olarak budur. Bu yöntem, oturum boyunca tüm dosya sistemi üzerinde tam etkileşimli bir düzenleyiciye root yetkileri verir; bu nedenle kaydetme isteminde yanlış yazılan bir yol, metninizin root yetkisiyle başka bir sistem dosyasının üzerine yazılmasına neden olabilir. Sadece ihtiyaç duyulan 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ı kullanıcıları ş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 disk alanı tükenmiş
findmnt seçeneklerinde ro bildirilmesi, yazma işleminin hiçbir zaman başarılı olamayacağı anlamına gelir. Dosya sistemi ya /etc/fstab üzerinden veya salt okunur bir bind mount ile bu şekilde bağlanmıştır ya da çekirdek bir disk hatasından sonra dosyayı salt okunur olarak yeniden bağlamıştır. İkinci durum daha ciddidir. sudo dmesg -T | tail -50 en son çekirdek mesajlarını gösterir, ancak yeniden bağlamaya neden olan girdi/çıktı ve dosya sistemi hataları son 50 satırda yer almayabilir. Çekirdek halka arabelleğinde (kernel ring buffer) tutulan tüm mesajları görmek ve yeniden bağlama öncesinde kaydedilen hataları incelemek için sudo dmesg -T komutunu tail olmadan çalıştırın. Onarım işlemi, dosya sistemi bağlı değilken (unmounted) gerçekleştirilen bir dosya sistemi denetimidir. Kök dizin (root) dışındaki bir dosya sistemi yerinde ayrılabilir ve denetlenebilir. Kök dizin için normal bir önyükleme yeterli olabilir: systemd, /etc/fstab dosyasında fsck geçiş numarası sıfırdan büyük olan her dosya sistemini denetler, initrd destekliyorsa kök dizini initrd içinde kontrol eder ve çekirdek komut satırındaki fsck.mode=force parametresi tam bir denetimi zorunlu kılar. VPS bu aşamaya kadar önyükleme yapamıyorsa, sağlayıcının kurtarma konsolu (rescue console) son çaredir.
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: Varsayılan olarak kullanılan ext4 dosya sisteminde 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 üzerinde hala gigabaytlarca boş alan görünse bile tüm inode'ları tüketebilir. XFS, inode'ları dosyalar oluşturuldukça atadığı için bu durum çoğunlukla ext4'e özgüdür. Alan tükendiğinde ve belirgin bir neden bulunamadığında, df ve du komutlarının dolu disk konusunda uyuşmaması başlıklı bölüm, silinmiş ancak hala açık olan dosyaların neden olduğu 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 nedenle normal kullanıcılar reddedildikten sonra root yazmaya devam edebilir. sudo bu durumda bir çözüm gibi görünse de disk tamamen dolar ve sorun daha kötü bir biçimde geri döner.
nano, yeni içeriği yazmadan önce dosyayı kısalttığı için, alanın yetersiz kaldığı bir yazma işlemi dosyanın eskisinden daha kısa kalmasına neden olabilir. Neredeyse dolu bir dosya sisteminde düzenleme yapmadan önce önemli bir yapılandırma dosyasının yedeğini alın. sudo cp -a /etc/nginx/nginx.conf /root/nginx.conf.bak kopyanın sahibini, grubunu ve izinlerini 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 yetkisiyle geri yazar; böylece düzenleyicinin kendisi hiçbir zaman root ayrıcalıklarına sahip olmaz. nano'yu seçmek için SUDO_EDITOR, VISUAL veya EDITOR değişkenlerini nano olarak ayarlayın. sudo nano de çalışır ancak bu yöntem, etkileşimli bir düzenleyiciye oturum süresince sistemdeki her yola root erişimi verir; 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 orijinalin yanında 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 şey. Dosya sistemi salt okunur (read-only) 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 bile dosyaya yazamaz. ext4 üzerinde, boş alan kalsa bile inode havuzu tükenmiş olabilir; bunu df -i ile görebilirsiniz. SELinux veya AppArmor, izin bitleri izin verse bile yazma işlemini reddedebilir. Denetim günlüğü genellikle bu reddi kaydeder, ancak SELinux dontaudit kuralları hiçbir şey günlüğe kaydetmeden yazma işlemini engelleyebilir. sudo semodule -DB, sorunu yeniden oluştururken bu kuralları devre dışı bırakır, sudo semodule -B ise tekrar açar.
Dosya hiçbir şekilde kaydedilmediğinde değişikliklerimi nereye koymalıyım?
Ctrl-O tuşlarına basın ve kendi ev dizininiz altında veya kullanıcınızın yazabileceği başka bir yerde, sahibi olduğunuz bir yol belirtin. Tampon bellek hala hafızadadır, bu nedenle 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 düzenlemelerim neden kayboluyor?
Yol bir mount noktası değilse, düzenleme container'ın yazılabilir katmanına gider ve container değiştirildiğinde bu katman atılır. Dosyayı bir bind mount veya volume'ün host tarafında düzenleyin ya da 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 ile gelen sayısal kullanıcı sahibiyle karşılaştırın: dosya host üzerindeki sahipliğini korur ve container sürecinin bu sahiplikle eşleşmesi gerekir.