ラベル Fedora の投稿を表示しています。 すべての投稿を表示
ラベル Fedora の投稿を表示しています。 すべての投稿を表示

2019/09/01

neovim で plugin を利用せずに sudo を使う

root 権限が必要なファイルを neovim や vim で編集する事があると思います。
その際、 sudoers で許可されているユーザならば
  • :write ! sudo tee % > /dev/null
で sudo を使って root として書き込むことができます。

ですが、 neovim では
  • :write ! sudo tee % > /dev/null
    • sudo: no tty present and no askpass program specified
    • shell returned 1
と言われて sudo が使えません。


解決策

以下のようなコマンドを定義することで対応できます。 このコマンドは vim と neovim の両方で利用できます。

vim で利用する場合は ~/.vimrc に追記します。
neovim で利用する場合は ~/.cofig/nvim/init.vim に追記します。


使い方

  • $ nvim /etc/hosts
    • root 権限が必要なファイルを開いて編集します。保存の際は
  • :SudoWriteCurrentBuffer
    • を実行します。
    • パスワードを入力すれば root で書き込む事ができます。


動作確認をした環境

大元の環境(vim と neovim で動作確認済)
  • OS: macOS Mojave 10.14.6 (18G95)
  • Homebrew: 2.1.11
    • Homebrew/homebrew-core: (git revision 883ee; last commit 2019-09-01)
  • neovim: v0.3.8
  • vim: 8.0.1365
  • sudo: version 1.8.17p1
    • Sudoers policy plugin version 1.8.17p1
    • Sudoers file grammar version 45
    • Sudoers I/O plugin version 1.8.17p1
  • docker: 19.03.1, build 74b1e89

    docker を使っていくつかの distribution でも動作を確認
    • Alpine linux: 3.10.2
      • neovim: v0.3.7
      • vim: 8.1.1365
      • sudo: version 1.8.27
        • Sudoers policy plugin version 1.8.27
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.27
    • CentOS: release 7.6.1810 (Core)
      • vim: 7.4.1099
      • sudo: version 1.8.23
        • Sudoers policy plugin version 1.8.23
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.23
    • Fedora: release 30
      • vim: 8.1.1912
      • sudo: version 1.8.27
        • Sudoers policy plugin version 1.8.27
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.27
    • Ubuntu: 18.04.3
      • vim: 8.0.1453
      • sudo: version 1.8.21p2
        • Sudoers policy plugin version 1.8.21p2
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.21p2
    • Debian: 10.0 (buster-20190812)
      • vim: 8.1.1401
      • sudo: version 1.8.27
        • Sudoers policy plugin version 1.8.27
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.27


    何故 neovim では sudo が使えないのか

    ここから先は先程の Vimscript を作るに至った経緯を書きます。
    興味のある方はご覧ください。

    まず sudo の error message
    • sudo: no tty present and no askpass program specified
    を見ると、 tty と askpass が無いと言っています。


    tty と askpass

    実際、vim では
    • : ! tty
      • /dev/ttys004 
    などが得られますが、 neovim では
    • : ! tty
      • not a tty
      • shell returned 1
    と言われてしまいます。

    askpass は使ったことが無いのですが、fedora の container で dnf search すると
    の様に、いくつかの askpass が確認できます。のでちょっと試してみます。
    • x11-ssh-askpass
    • openssh-askpass
    • ksshaskpass
    という感じで全然起動してくれません。
    ですがエラーの内容的に display を開こうとしているのが分かります。
    なので、おそらく GUI で password を聞くような物だと思われます。


    askpass を作る

    askpass について調べていると、どうやら
    • password を stdout に出力するもの
    であることが分かりました。

    よって
    • neovim 内で password を取得
    • password を stdout に出力する
    • password の履歴はどこにも残さない
    ようなものを作れば解決できそうです。

    それで完成したのが /tmp/askpass を作るこの Vimscript です。

    本当はファイル名は固定でなく tempfile 的な物で対応するなど、改善点はいくつも存在するかと思います。
    ですが私は Vimscript に明るくないので、"3つの条件を満たして動けばOK" という条件で作成しました。
    他により良い対応方法があればご指摘頂けると幸いです。


    その他の解決策

    調べた結果、 suda.vim というプラグインがあるようです。
    また、他にも sudo.vim など、似たようなプラグインはいくつかあるらしいです。

    これを使わなかった理由としては
    • docker のコンテナ内で作業をする事が多々ある
    • init.vim を配置するスクリプトは既にある
    • plugin を install するスクリプトはまだ無い
    • 全コンテナに plugin を入れるのも面倒だし結構サイズがある
      • $ du -sh ~/.config/nvim/repos
        • 100M    /Users/atton/.config/nvim/repos
    などがあります。

    また、"sudo が使えるならこの際 root になってしまう" という解決策もあるのですが
    • 前述した理由の後半3つ
    • 複数人数のユーザが使う環境だと、 /root 配下に自分専用の設定を置くことになる
    のでこちらも無しで。

    他には、 "sudoers で NOPASSWD を設定する" という解決策もあります。
    が、sudo を no password でガンガン使えば実質 root で作業しているのと変わらず、危険すぎるのでこちらも無し。

    ということでこの Vimscript を書くに至った、という訳なのです。


    おまけ: 環境変数の unlet

    スクリプト内部では askpass の場所を示す SUDO_ASKPASS を設定している部分があります。
    具体的には
    • let $SUDO_ASKPASS  = s:askpass_path
    ですね。

    この環境変数を定義していると、 sudo -A した際に指定したファイルが実行されます。
    一応、 :SudoWriteCurrentBuffer の実行後にはなるべく元の環境に戻すために
    • unlet $SUDO_ASKPASS
    を書いていた時もありました。

    ですが動作確認中、 Vim 8.0.1365 で unlet 時にエラーが出てしまいました。
    また 、-A を指定しなければ sudo の動作は変わらないので 、残っていても無害と判断して unlet しない形になりました。


    おまけ: shebang を指定しないとどうなるのか

    ちなみに askpass の shebang を消すと
    • sudo: unable to run /tmp/askpass: Exec format error
    • sudo: no password was provided
    と言われる為、きちんと書いておく必要があります。


    おまけ: x flag を付けないとどうなるのか

    setfperm(s:askpass_path, "rwxr-xr-x")  をせずに 644 のままだと
    • sudo: unable to run /tmp/askpass: Permission denied
      • sudo: no password was provided
      と言われるので、こちらもきちんと指定しておく必要があります。


      参考

      2013/10/14

      vim-enhanced を yum で入れる際に注意すること

      vagrantbox.es な Fedora19 でのログ。
      Fedora19 でのデフォなのか、 box 化された Fedora19 の設定だったのかは謎だけれど。


      vim が vim-minimal だったので vim-enhanced を入れようと
      $ yum install vim-enhanced
      すると vim-common が vim-minimal と conflict とか出てくる。
      Transaction check error:
        file /usr/share/man/man1/vim.1.gz from install of vim-common-2:7.4.027-2.fc19.x86_64 conflicts with file from package vim-minimal-2:7.3.1314-1.fc19.x86_64

      ってな訳で vim-minimal を消す
      $ yum erase vim-minimal
      そうすると依存の関係で sudo が消える。 たぶん visudo とかの関係。
      Running transaction
        Erasing    : sudo-1.8.6p7-1.fc19.x86_64              1/2
      warning: /etc/sudoers saved as /etc/sudoers.rpmsave
        Erasing    : 2:vim-minimal-7.3.1314-1.fc19.x86_64    2/2
        Verifying  : sudo-1.8.6p7-1.fc19.x86_64              1/2
        Verifying  : 2:vim-minimal-7.3.1314-1.fc19.x86_64

      sudo を erase すると /etc/sudoers が消えるので /etc/sudoers.rpmsave にバックアップされるみたい。
      なので vim-enhanced を入れる時に sudo も入れて、 /etc/sudoers を元に戻すと元通りのはず
      $ yum install vim-enhanced
      $ yum install sudo
      $ mv /etc/sudoers.rpmsave /etc/sudoers
      これで sudo できるし vim も enhanced になってめでたしめでたし。
      というか sudo 消えるのこわい。

      2013/10/11

      Vagrant で box が add できない

      時系列は前後するのですが、 Vagrant 導入時にちょっと引っかかった内容。

      Vagrant は ruby base だと聞いていたので導入は
      $ gem install vagrant
      でやったところ、入るのは 1.0.x 系列らしい。

      1.0.x 系列で CentOS の最新版や Fedoraの最新版の box を add しようとすると、ダウンロード終了後の展開時に
      Failed to untar the box file. This is usually because you're
      attempting to add a box that isn't a valid box file. Please
      double check that the box file is properly packaged.
      とか言われて落ちる。
      VAGRANT_HOME の関係で、ホームディレクトリでやると良い  とか それでもダメだったからバージョン低い box でやった とかいろいろ対策があるみたい。
      私は前者はダメで、後者の方のバージョンが低い CentOS の box を指定すれば add できた。

      実際何が原因だったかと言えば、 vagrant のバージョンでした。最新だと問題無し。
      Vagrant 公式の最新は 1.3.4 で、これは gem からだと入らないみたい。
      dmg を落としてきてインストールする必要がある。

      インストールした Vagrant は /Applications/Vagrant/bin くらいに command があるけれど /usr/bin に symlink が貼られている様子。
      なので、 gem の方をアンインストールして dmg な /usr/bin/vagrant の方を優先するようにすると実行できる vagrant が 1.3.4 に。
      1.3.4 だと fodora19 の box も問題無く add できた。
      gem の方を uninstall しなくても良いかもしれないけれど、パスの優先度を変えたり追加するのも面倒だったので gem の方を消すことで対処。

      とりあえず最新の fedora を box 化するような人が古い Vagrant 使うはずがなかったんやー、みたいなオチで一つ。

      Vagrant + Puppet で Fedora 19 に MySQL を入れる

      MySQL な環境を構築しよう、ということになったけれど、どうせなので Vagrant でやることに。
      と思ったら非常にいろいろハマったのでメモ。

      環境

      • OS X Mountain Lion
      • Vagrant 1.3.4

      Vagrant のインストール

      Vagrant のサイト から最新な 1.3.4 をインストール。
      ちなみに /usr/bin/vagrant くらいにシンボリックリンクが貼られるので、 rbenv な vagrant は uninstall した。


      Fedora 19 を入れる

      Vagrantbox.es から最新な Fedora19 を使うことに。
      $ vagrant box add fodora-19 https://dl.dropboxusercontent.com/u/86066173/fedora-19.box
      これで box がダウンロードされる。
      box は直接起動する訳じゃなくて、
      $ vagrant up
      した時にコピーされて起動するみたい。
      なので
      $ vagrant destroy
      しても box そのものは消えない。



      Puppet で MySQL を入れる

      入れようと思ったら大量にハマるなど。
      以下に導入ログとトラブルシュートなログ類。

      Puppet の Install

      $ vagrant plugin install puppet
      くらい。 gem からでも入るっぽいけれど、vagrant な例に習って gem の puppet は uninstall した。

      Puppet の設定

      Vagrantfile に書かれているやつをコメントアウトする。
        config.vm.provision :puppet do |puppet|
          puppet.manifests_path = "manifests"
          puppet.manifest_file  = "mysql.pp"
        end
      とか。
      mysql.pp とかはマニフェストの名前。何でも良いはず。
      ディレクトリ構成は
      .
      ├── Vagrantfile
      └── manifests
          └── mysql.pp
      みたいな感じになる。
      この状態で mysql.pp に設定を書いていく感じ。

       

      Puppet の実行

      puppet で環境を構築するのは provision すると良いみたい。
      up の時に provision も実行するなら
      $ vagrant up --provision
      しないなら
      $ vagrant up --no-provision
      1.3 系だと up は初回は provision が走って、次回以降は走らないのがデフォらしい。
      ちなみに up してる時にも
      $ vagrant provision
      で provision が実行されて puppet が走る。



      エラーログ

      ここからエラーログ

      IP アドレスが取得できないっぽい

      $ vagrant provision
      した時に
      Running Puppet with mysql.pp...
      Could not retrieve macaddress: undefined method `each_line' for nil:NilClass
      Could not retrieve macaddress: undefined method `each_line' for nil:NilClass
      Could not retrieve macaddress: undefined method `each_line' for nil:NilClass
      Could not retrieve ipaddress6: undefined method `scan' for nil:NilClass
      Could not retrieve netmask: undefined method `split' for nil:NilClass
      Warning: Could not retrieve fact ipaddress
      とか怒られる。
      IP が見えてないっぽい。
      fedora19 には最初から ifconfig とかが入ってないらしいので
      $ yum install net-tools
      しておく必要があるみたい。
      この辺も manifest に書いておくと怒られない。
      ちなみにこう怒られたのは yum update の時。

      hostname と DNS 周りが変らしい

      warning: Could not retrieve fact fqdn
      とも言われた。
      この辺は hostname が fqdn に対応してない(のかな?)っぽいのと、dnsな設定が変らしい。
      どうやら VM の domain が適切に設定できてないとダメらしい。
      /etc/resolve.conf に domain な記述が無いといけないらしい。
      んで、 resolve.conf は vagrant が勝手に設定するらしいので、実行するホストの環境によっては設定されなかったりするっぽい。
      generated by NetworkManager とか書かれてたので vagrant 側じゃなくて fedora 側が勝手に作ってるのかもしれないけれど。
      無理矢理 /etc/hostname に hostname を書いて、 /etc/resolve.conf に domain を書くと出ない。
      ちなみに hostname と dnsdomainname コマンドがおかしい時に出てくるエラーらしい。
      あと vagrant ssh して
      $ factor | grep fqdn
      すると、エラーが出る方には fqdn な値が無かったり。
      この辺設定できるとエラーは出ないのかもしれない。

      そもそも MySQL が Fedora19 に無い

      $ yum install mysql
      とかがダメで
      $ yum intall community-mysql
      とからしい。
      しかも接続してみると MySQL じゃなくて MariaDB とか出てくる。
      調べてみると fedora19 から MySQL の default が MariaDB だとか。


      Vagrantfile と manifests/mysql.pp

      書き方はググりながらだったので省略するとして、最終的にできた Vagrantfile と manifest はこんな感じ。
      mysql をインストール + 有効化とパッケージのアップデートをしてくれます。
      あと hostname の設定。


      最終的に

      $ vagrant up
      $ vagrant provision
      で起動と環境構築をしてくれるようになりました。
      便利だけれど実行できるようになるまで大分ハマった。
      この辺ささっとできると良いのかなーうーん。