Jak řešit "povolení odmítnuté" při použití sudo s přesměrováním v Bash?

117

Když používám sudo k úpravám souborů, pravidelně dostávám "oprávnění odmítnuta".

Například myš je nervózní a pomalá, takže chci vypnout hlasování:

sudo echo "options drm_kms_helper poll=N">/etc/modprobe.d/local.conf

Já jsem vyzván k zadání hesla a pak dostanu:

bash: /etc/modprobe.d/local.conf: Permission denied

Takže jsem se pokoušel provést dočasnou změnu, která by zakázala hlasování pomocí:

sudo echo N> /sys/module/drm_kms_helper/parameters/poll

Systém opět odpověděl:

bash: /sys/module/drm_kms_helper/parameters/poll: Permission denied

Nějaké nápady?

    
dané Jack 19.12.2012 05:12

6 odpovědí

127

Přesměrování výstupu (pomocí operátoru>) provádí shell, nikoliv echo . Musíte se přihlásit jako root

sudo -i

Potom můžete použít přesměrování

echo N> /sys/module/drm_kms_helper/parameters/poll

Jinak můžete spustit bash řetězec s sudo

sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"
    
odpověděl shantanu 19.12.2012 05:22
71

Přesměrování výstupu provádí shell , ze kterého byl vyvolán příkaz . Takže všechno rozdělíte na bity, tady se děje *:

  • shell vyvolásudo echo "options drm_kms_helper poll=N", který provede příkazsudo secho "options drm_kms_helper poll=N" příkazového řádku

  • sudo požádá o heslo, otevře shell superuser a zavoláecho "options drm_kms_helper poll=N", který spouští příkazecho předáním"options drm_kms_helper poll=N"

  • Echo, které běží s oprávněnímiroot, vytiskne řetězec na standardní výstup.

  • Příkazecho se ukončí, ukončí shell superuser, ukončísudo

  • shell, ze kterého byl vyvolán příkaz, shromažďuje výstup a pokusí se přesměrovat na/etc/modprobe.d/local.conf, který je zapisovatelný pouze kořenem. Dostane chybu "odmítnuto oprávnění".

Způsoby, jak to opravit, naleznete v odpovědi na @shantanu.

(*) - zatímco výše uvedená sekvence pomáhá pochopit, proč příkaz selhal, ve skutečnosti se věci staly poněkud mimo řád: původní shell si všimne přesměrování a pokusí se otevřít soubor pro psaní před vyvolánímsudo ... příkaz. Při otevření souboru selže shell dokonce nevyvolá příkaz, který měl zapsat do souboru (díky @PanosRontogiannis pro to upozorní).

Zde je rychlý test:

$ touch ./onlyroot.txt
$ sudo chown root:root ./onlyroot.txt
$ sudo bash -c "whoami | tee who.txt" > onlyroot.txt
bash: onlyroot.txt: Permission denied

Při testu nadwhoami | tee who.txt se vytvoří soubor s názvemwho.txt obsahující slovo "root". Pokud však v přesměrování volání selže přesměrování výstupu, chybí také soubor "who.txt", protože příkaz nebyl vyvolán.

    
odpověděl Sergey 19.12.2012 06:19
55

Přidání k odpovědi Shantanu:

... Nebo můžete použít následující příkaz tee :

sudo tee /sys/module/drm_kms_helper/parameters/poll <<<10

nebo pokud je jeho výstup:

echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/poll
    
odpověděl Untitled 19.12.2012 07:50
13

Přístup, který jsem zde neviděl, je prostě spustit celou příkazovou řádku ve svém vlastním shellu. Samotnásudo manpage uvádí příklad tohoto přístupu:

  

Vytvořte seznam použití adresářů v oddílu / doma. Všimněte si, že to spouští příkazy v dílčím shellu, aby provedly práci s přesměrováním souborů cd a souborů.

$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
    
odpověděl kojiro 19.12.2012 14:53
3

sudo dd of=

Připojit podle potřeby:

echo inbytes | sudo dd of=outfile oflag=append conv=notrunc

nebo obnovte soubor od začátku:

echo inbytes | sudo dd of=outfile

Výhody:

  • hezčí nežtee protože žádné/dev/null přesměrování
  • hezčí nežsh, jelikož neexistuje žádná explicitní podružná (ale implicitní pro přesměrování)
  • dd má mnoho výkonných možností, např. status=progress pro zobrazení postupu přenosu

funguje, protože sudo předává příkazu stdin.

    
odpověděl Ciro Santilli 新疆改造中心 六四事件 法轮功 28.05.2017 08:39
2

Další možností je použít dočasný soubor. To je užitečné v bash skriptu.

temp=$(mktemp)
echo "Hello, world!" > $temp
sudo cp $temp /etc/wherever
    
odpověděl user545424 29.07.2014 17:51