それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

gitlab-runner を削除する

gitlab-runner を削除したい

不要になった runner や、名前をつけ間違えたrunnerを削除したい。

でもGitLabのWeb側で削除したけど、残ってたので、よくわからなったのでまとめた。

gitlab側で削除されたランナーを見つけて消す方法

sudo gitlab-runner  verify --delete

実際に消したところ。

takuya@sakura:~$ sudo gitlab-runner  verify --delete
Running in system-mode.

Verifying runner... is alive                        runner=b1c83735
Verifying runner... is alive                        runner=00b62a52
Verifying runner... is alive                        runner=90cd2aef
Verifying runner... is alive                        runner=a4facb27
ERROR: Verifying runner... is removed               runner=5be0fea6
Updated /etc/gitlab-runner/config.toml

消した結果、一つ減りました。

takuya@sakura:~$ sudo gitlab-runner  verify --delete
Running in system-mode.

Verifying runner... is alive                        runner=b1c83735
Verifying runner... is alive                        runner=00b62a52
Verifying runner... is alive                        runner=90cd2aef
Verifying runner... is alive                        runner=a4facb27

--delete オプションで簡単です。unregister はgitlab-server 側から削除される前なら使えるんだけど、削除後はコレが一番簡単だと思う。

remove とか探したけどないし、 stop / start も違うしちょっと迷ったのでメモ。

yarn install/npm i でnode-gypがエラーになったときの原因が調べたらpyenvだった

いつものように npm i 決めてたら

エラーになりました。

node-pre-gyp WARN Tried to download(404): https://fsevents-binaries.s3-us-west-2.amazonaws.com/v1.2.4/fse-v1.2.4-node-v67-darwin-x64.tar.gz
node-pre-gyp WARN Pre-built binaries not found for fsevents@1.2.4 and node@11.0.0 (node-v67 ABI, unknown) (falling back to source compile with node-gyp)
gyp ERR! configure error
gyp ERR! stack Error: Command failed: /Users/takuya/.pyenv/shims/python2 -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack pyenv: python2: command not found
gyp ERR! stack
gyp ERR! stack The `python2' command exists in these Python versions:
gyp ERR! stack   2.7.15

python2じゃないってエラーじゃん。

macOS の標準システムをターゲットに作られているのでpyenv が入っていたら消す。

対策

該当プロジェクトに入って

pyenv local  system

npm するまえに、pythonをシステム標準のものにする必要がある。怖い。

node-gyp がエラーになりだすと、gyp 関連で落ちてるのか、node のバージョンで落ちてるか、本当にわからない。

たいていは fsevent でエラーになるんだけど。npm マジ困る。

gitlab のログインをGoogleにする。(ユーザー初期登録も

gitlab の初期登録後に、Google ログインを有効にした

Google Oauth を使うと、Gitlab側でいちいちユーザーを作らずに済むので便利。

認証の設定について

Google OAuthの設定で2つの連携設定がある。

  1. 登録済ユーザーが各自で認証Googleアカウントを設定する
  2. 未登録ユーザーがGoogleでログインしたらユーザー作成

必要なもの

独自ドメインgoogle oauth で必要です。

httpsはあったほうが良い。っていうか今どきは当たり前。

google oauth の取得方法

Google アカウントでAPI Consoleにログインして、Google のOAuth用のWeb credential を作る。

  • API コンソールにログイン
  • プロジェクトを作成(なければ)
  • credential を作成
  • web アプリケーションで作成
  • ドメインに gitlab-ce のドメインをいれる。

oauth が準備できたら

gitlab の設定をする。

omnibus の場合 /etc/gitlab/gitlab.rb

Google Oauthでログインしたユーザをすぐに有効にする。

この設定が大事。

gitlab_rails['omniauth_block_auto_created_users'] = false

この設定を true にするとユーザ登録はできてもブロックされる。

ちなみにデフォルトはブロックです。 GoogleのOAuth連携できるユーザーはすべて無条件で許可されてしまいます。

この設定をfalse にすると google で認証されたユーザーは無条件に許可されるので、Gitlab側の設定で「ドメインに制限」を掛ける必要がある。

Gitlab側の設定では

  • /admin/application_settings から、
  • Sign-up restrictions
  • Whitelisted domains for sign-ups

とたどって許可したいドメインだけに限定しないと大変なことになる。

gitlab 側の設定

### OmniAuth Settings
###! Docs: https://docs.gitlab.com/ce/integration/omniauth.html
gitlab_rails['omniauth_enabled'] = true
gitlab_rails['omniauth_allow_single_sign_on'] = ['google_oauth2']
# gitlab_rails['omniauth_allow_single_sign_on'] = ['saml']
# gitlab_rails['omniauth_sync_email_from_provider'] = 'saml'
# gitlab_rails['omniauth_sync_profile_from_provider'] = ['saml']
# gitlab_rails['omniauth_sync_profile_attributes'] = ['email']
# gitlab_rails['omniauth_auto_sign_in_with_provider'] = 'saml'
gitlab_rails['omniauth_block_auto_created_users'] = false
# gitlab_rails['omniauth_auto_link_ldap_user'] = false
# gitlab_rails['omniauth_auto_link_saml_user'] = false
gitlab_rails['omniauth_external_providers'] = ['google_oauth2']
gitlab_rails['omniauth_providers'] = [
  {
    "name" => "google_oauth2",
    "app_id" => "xxxxxxxxxxxxxxx0dse47iulk.apps.googleusercontent.com",
    "app_secret" => "xxxxxxxxxxxxxxxxxx",
    "args" => { "access_type" => "offline", "approval_prompt" => "" }
  }
]

ログインチェック

設定したら gitlab を reconfigure してログインをチェックする。コレが大事。

ぱぱっとやれば大丈夫。

参考資料

https://docs.gitlab.com/ee/integration/google.html

LVMのVG構成をバックアップする

VGの構成をバックアップするコマンドがある。

VG構成はディスクを再利用するときにどうなってたかわからないと再現が難しい。とくに複数のPVをVGにまとめてから切り出しているときなど。

takuya@:~$ sudo vgcfgbackup
  Volume group "data" successfully backed up.
  Volume group "home" successfully backed up.

vgcfgbackup を使って構成をバックアップとっておくとちょっとだけ安心できる。

リストア(復旧・リカバリ)するには vgcfgrestore を使う。

vgcfgrestore -f /etc/lvm/backup/home home

試したいけど、LVM環境を作って試すのがめんどくさいのでメモ程度。

GitlabのSSHアクセスで、標準22以外のポートを使えるように設定する

gitlabのssh ポートを変えたい

Gitlabでpushするssh のポートを自分の独自のポートにしたい。

自宅サーバーで運用してたり、セキュリティ的な問題でポート22番以外を使ってるとき、gitlabでsshを使おうとするとデフォルトの22ポートになるので不便。

かといって、.ssh/config で設定するのもめんどくさい。

調べたらできることがわかった。gitlab ホント柔軟に使えるな。

22 → 2222

設定ファイルを書き換えて再起動でオッケ

/etc/gitlab/gitlab.rb

gitlab_rails['gitlab_shell_ssh_port'] = 2222

再起動

gitlab-ctl reconfigure

これでコピペするURLにポートが含まれるようになる。わーい。

参考資料

MacでIPv6をオフにして無効化する

IPv6をオフにする。

フレッツ光ネクストを使っていると、例の壊れたv6がWiFi経由で割り振られて辛い。

個人的には、v6のほうが空いているし、フレッツIPv6網の通信は高速なので使いたいんだけど、まだまだv4です。v6→v4 のフォールバックが発生するのが悲しい

内線外線がないGWで守れない通信は正直つらいところ。フレッツ機器でv6を使いたいし網内折返しをフィルタリングをしたいんだけど、、、不便だよね。

もうv6オフにしちゃおう

sudo networksetup -setv6off Wi-Fi

WiFiの名前は

 networksetup -listallnetworkservices

これで取得することができる

参考資料

  • networksetup -h

sudo su実行後も環境変数を維持する

suの実行後にカレントディレクトリを維持したい

su を実行するとカレントディレクトリが変わってしまうので、いまいるディレクトリやeditor 変数をそのままに 別ユーザーになりたい。

sudo -E を使う

sudo にオプションを付ければ、カレントディレクトリなど現在の環境をそのまま維持してsu することができる。

sudo -E su

man sudo から抜粋

      -E, --preserve-env
                   現在の環境変数をそのまま保持するのがユーザの意向だと、セキュリティポリシーに指示する。 ユーザが環境を保持する許可を持っていない場合は、 セキュ                                                                            
                   リティポリシーがエラーを返すことになるだろう。                                     

/etc/sudoers の設定と密接な関係

環境変数の設定と維持は sudoers の設定と密接な関係にある。

私の場合、sudo 実行時に余計な環境変数を持ち込みたくないのでリセットしている。というかディストリビューションのデフォルトはほとんど場合が環境変数を初期化するはずだ。

sudoers

Defaults  env_reset

この設定があれば、 /etc/environment の設定で環境変数がリセットされるはずだ。

sudoersで環境変数を維持することにする?

sudo -E を毎回付けるのが面倒な場合は env_reset を消してしまえばいい。 

個人用のLinux Desktop だと便利だと思う。 ただ、共有のサーバーなどでこれをやると知らないあいだに alias 書き換えられてたりして、気づかずマルコマンドを実行する恐れがあって怖い。

なので、他の設定 etc_keep や set_env を sudoersで組み合わせて必要な環境変数だけ持ち込むのがベターだとおもう。これらのついては、はどこか別の機会に

参考資料

  • man sudo
  • man 5 sudoers

関連資料

http://takuya-1st.hatenablog.jp/entry/2018/10/17/023000

xargsで複数行のコマンドを実行する方法

xargs で複数行のコマンドを実行したい。

出来ない・・・

ls *.txt  | xargs -I@ echo @ ; sleep 1

forループならできるんだけど、for ループだとどうしても不便。

xargs でシェルコマンドを作って渡す.

xargs だと限界があるので、もうシェルの文字列にして渡すしか、他に選択肢がない。

ls *.txt  | xargs -I@  sh -c 'echo @ ; sleep 1'

これなら動くんです。動くんです。

xargs が1つ実行するたびに、 sh -c 'echo @ ' の@ の部分にファイルを文字列として入れて渡してくれる。

bash でもいい

sh だと機能が少ないので、bashにしてやるという手段も取れる。

ls *.txt  | xargs -I@  bash -c 'echo @ ; sleep 1'

条件分岐も

もうここまできたら、なんでもあり。シェルに文字列渡すんでス。ここなら何でもありです。条件の入力だってできちゃう。

ls *.txt  | xargs -I@  bash -c ' [[ @ =~ 2017 ]]  echo @ ; sleep 1'

脱 for文

これで、for がなくても戦える。

なんだけど、ここまでする必要あるかなぁ。コマンドを履歴に残したいとかパラレルに実行したいときには相当便利だけど、コードメンテしにくい。。。両刃の剣か。

参考資料

HTTPSサイトからの遷移時に内部サイトのリファラがもれないようにする。サーバー側設定Referrer-Policy

nginx をつかってブラウザにリファラをおもらししないように命令する

社内のファイルサーバーのリファラURLが漏れると恥ずい。いやまずい。

何がまずいかというとファイル名が漏れてしまったり、アクセス元のURLとして晒されたり、検索インデックスに追加される恐れがあるからだ。

server {
    add_header Referrer-Policy no-referrer always;
}

これを書くと、ブラウザがリファラを送らなくなる。一般的なブラウザの場合だけどね。 サーバー側で制御できるものはしちゃったほうが良いね。

リファラでファイル名がバレるとそれを使っってターゲット・フィッシングメールが作れるもんね。

選択肢

origin
same-origin
strict-origin

origin

基本的に使わない。このサイトからリファラを送るならURLにパスを入れないでくれ。 リファラURLでなく、リファラドメインだけが送られる。

strict-origin

基本的にコレ。このサイトでは同一ドメインリファラを送ってくれ。 HTTPでセットされたとき、HTTP→HTTP(s)で送られる、HTTPSでセットされたとき、HTTPSHTTPSのみ、HTTPS→HTTPはリファラ対象外。

no-referrer

このサイトではリファラを絶対送らないでくれ。というヘッダ。

詳しくは、参考資料のMDNページ

参考

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Referrer-Policy

tesseractでPDFを検索可能にしてみる

tesseract を使ってPDFをOCRする

https://pypi.org/project/pypdfocr/ というツールを見つけたので、使ってみる

残念なお知らせです。

python 3 系ではシンタックスエラーで動きません。

インストールのログがこちら。

takuya@deskew$ pip install pypdfocr
Collecting pypdfocr
  Using cached https://files.pythonhosted.org/packages/c3/23/1bf42cb12af63d498fcd425882815c21efef37800514dbad9fa28918df5e/pypdfocr-0.9.1.tar.gz
Requirement already satisfied: pillow>=2.2 in /Users/takuya/.pyenv/versions/3.7.0/lib/python3.7/site-packages (from pypdfocr) (5.3.0)
Collecting reportlab>=2.7 (from pypdfocr)
  Using cached https://files.pythonhosted.org/packages/d8/d5/583e6235d0c690c2cda2cd080c60413fbf7be8d8e012e003087202edfb50/reportlab-3.5.9-cp37-cp37m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl
Collecting watchdog>=0.6.0 (from pypdfocr)
  Using cached https://files.pythonhosted.org/packages/bb/e3/5a55d48a29300160779f0a0d2776d17c1b762a2039b36de528b093b87d5b/watchdog-0.9.0.tar.gz
Collecting pypdf2>=1.23 (from pypdfocr)
  Using cached https://files.pythonhosted.org/packages/b4/01/68fcc0d43daf4c6bdbc6b33cc3f77bda531c86b174cac56ef0ffdb96faab/PyPDF2-1.26.0.tar.gz
Collecting evernote (from pypdfocr)
  Using cached https://files.pythonhosted.org/packages/f9/6b/877f8edef8ef040d32eb38f3bf6322ba334de9d10614d8db9d869c162fc1/evernote-1.25.3.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/private/var/folders/ff/fc49g5wd6xncjylvwy4tdygc0000gn/T/pip-install-yx8p73r2/evernote/setup.py", line 6
        exec x
             ^
    SyntaxError: Missing parentheses in call to 'exec'

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /private/var/folders/ff/fc49g5wd6xncjylvwy4tdygc0000gn/T/pip-install-yx8p73r2/evernote/

しかたないので、pyenv で切り替えて使ってみることにしたい。

ちょっと困りますよね。python2系は流石にちょっとと。でも動けばいいしPDFをぱぱっと扱えるならpython2でも我慢する。

pyenv global 2.7.15
pip2 install pypdfocr

tesseractが無いばあい、いれる必要がある。

brew install tesseract

OCR をしてみる

pypdfocr my.pdf

うーん、めっちゃ時間かかる。時間かかる割にtesseractの調整をしてないから精度がいまいちな気がする・・・・・日本語も取れないし。tesseractをちゃんと設定しないとダメだし、所詮OCRなので・・・諦める。

参考資料

https://pypi.org/project/pypdfocr/

画像をpdfに変換する

画像を、PDF(画像埋込)に変換する

img2pdf を使ってみる

img2pdf のインストール

img2pdfは pip で提供されている pythonのコマンドなので pip でインストールする。

pip install img2pdf

これで準備出来た。

使ってみる。

 ls *.jpg | xargs -I@ img2pdf @ -o @.pdf

ちゃんとしっかり変換できた。

pdf を1枚にまとめる。

pdftk *.pdf cat output  combined.pdf

pdf は1枚ずつ変換してPDFにまとめたほうが良いっぽい

2019-07-27 追記

このコマンドは、PDF にJPEGをそのまま埋め込みして変換するので、再エンコードが発生せずに、元のJPEGのまま埋め込める。

言われてみたらたしかに、そうだった。その視点はなかった。

そうだよね。確かこのコマンドを調べて記事にした頃、magick だと変換するので遅いし劣化するから困って無圧縮(無変換)で探してたかもしれない。メモから記事にしたのですっかり忘れてる。

参考資料

Macbook"13 を限界突破して解像度(2880x1800)を無理やりで使う。DisplayMenu

ThinkPadとか見てたらめっちゃ文字小さくてデスクトップが広くて羨ましい。

わたし、ぜんぜん老眼じゃないですよ。小さい文字のほうが見やすくて好きなくらいです。

MacbookRetina解像度をオフにして、Windowsのノートパソコンのような極小な文字で、広大なデスクトップを確保したいと思いました。

だって、小さいって良いことだよね。 小っちゃいって事は便利だねっ

Mac App Store の Display Menu を使うと簡単です。

Display Menuのアプリケーションを使うと、Windowsの人みたいに、限界まで小さくしたデスクトップ環境を確保できます。

f:id:takuya_1st:20181031022201p:plain

Retina解像度をオフにしたらこんな感じ、広い、ただただ広い。ほんとひろい。

これ、MacbookProの13 なんですよ。2560x1600なんですよ、 2880x1800まで引っ張り出せるんです。

f:id:takuya_1st:20181031022204p:plain

欠点

Retina解像度じゃなくなる。

マウス移動が大きくてトラックパッドが足りなくなる。

でもね 2560x1600とか 2880x1800とかにもなると、Retina解像度じゃなくても気にならない。 でもね、MBP 2016 以降の大きなトラックパッドだと快適だったりする。

眼がおかしくなる。ただ、長時間やってるとめっちゃ疲れるんで、たくさん文章を書くとき、集中したいとき、めんどくさいコードを追いかけるときに限定しても良いかもしれない。

付加価値的なメリット;覗き見防止

覗き見防止のフィルタを貼るくらいなら、いっそ限界まで最大の解像度にしたらどうでしょうか。広くて仕事捗るし、画面の文字が小さくて1メートル以上離れたら多分見えない。

なんなら電車で、横に座ってる人でも視認は大変なレベルだと思います。

RetinaMBAだと意味ないよ

RetinaMBAでコレを利用して解像度が増えないというレビューを見かけたんですが、Retinaを切ってドットbyドット(液晶モニタの本来の解像度)にするので、MBAの人はMBA Retianaを座して待つしか無いです。(2018-10-31 発表があり、Retina MBA がついに出ました)

課金

課金したらRetina解像度に戻せるメニューが増えるようです。 いちいち環境設定を開かなくて良くなるのは便利ですね。

参考記事

www.atmarkit.co.jp

ものすごく疑問なんだけど、なぜこの記事が、Windows Insiderにかかれているんだろう

xargs で実行前に確認のY/Nを実行する interactive

xargs のコマンド実行前に確認する

xargs -p 

これで、毎回確認できる

使ってみた例

takuya@temp$ ls *.jpg | xargs -p -I@ --verbose mogrify -crop 2886x3700+0+0 @ 
mogrify -crop 2886x3700+0+0 out-000.jpg  ?...y
mogrify -crop 2886x3700+0+0 out-000.jpg
mogrify -crop 2886x3700+0+0 out-001.jpg  ?...y

コマンド実行前に確認のプロンプトで確認入力を促せる。

正直使い所が難しい

xargs を使うときは、大量に実行したいときがほとんどなので、ちまちまとY/N尋ねられる用途とは相容れないと思うのね。

ただ、ある程度のファイル数が少ないときで、シェルスクリプトから削除を実行するときにインタラクティブに質問するのは良いと思います。たとえば、ゴミ箱を空にするときとか。

一番便利なのは、コマンド確認

とりあえず、-p をつけて実行コマンドを確認してから、 Ctrl-C で抜けて、その後-p を外して実行すれば、「1つ目」のコマンドを確認でき、1つ目さえ通ればあとは問題ない場合が多いので、ミスが少なくなる。

https://unix.stackexchange.com/questions/300095/how-do-i-get-xargs-to-show-me-the-command-lines-its-generating-without-running

xargs 実行するコマンドを確認表示してどこまで進んだかを見やすくする

xargs 便利ですよね。

コマンドを明示的に1つずつ実行したり、ファイルをまとめて実行したり。実行する子プロセス数(スレッド)を指定できたり。

まとめて処理しているときにどこまで処理しているかを見ながらやってほしい

たとえば、rsync の場合だと rsync --progress すると転送情強のファイル名が見れるじゃん。
同じように、今実行しているファイルがどれか、進捗をxargs でできると楽しそう。

オプション -t

次に実行するコマンドを表示してから実行してくれる -t を使うとできる

これで、表示がでるので何を実行しているのか確認ができる。

たとえば、画像を1000枚変換するときに、今何枚目を実行しているかわかる。

takuya@temp$ ls *.jpg  | xargs -t -I@ -P 1 mogrify -crop 2886x3700+0+0 @ 
mogrify -crop 2886x3700+0+0 out-000.jpg
mogrify -crop 2886x3700+0+0 out-001.jpg
mogrify -crop 2886x3700+0+0 out-002.jpg
mogrify -crop 2886x3700+0+0 out-003.jpg
mogrify -crop 2886x3700+0+0 out-004.jpg
mogrify -crop 2886x3700+0+0 out-005.jpg
mogrify -crop 2886x3700+0+0 out-006.jpg
mogrify -crop 2886x3700+0+0 out-007.jpg
mogrify -crop 2886x3700+0+0 out-008.jpg
mogrify -crop 2886x3700+0+0 out-009.jpg

例2

たとえば、フォルダに対して、なにか処理をして、その結果が必要なとき。 このときは、標準出力を分けてあげればいい。

takuya@tmp$ find -type f | xargs -I@ -P 5 -t md5sum @ >> md5-list.txt

もう ps をwatch しなくていい。

たくさんのファイルを処理中は、ps を見たりしてたんだけど、Verboseに今の実行コマンドをプリントして表示してくれるなら、めっちゃ便利。

2021-03-17

標準出力を分ける方法を追記

参考資料

https://stackoverflow.com/questions/842401/is-xargs-t-output-stderr-or-stdout-and-can-you-control-it

nginx で proxyPassReverse的なのを実現する。

apache のproxyPassReverseって便利だよね。

とくに静的ページを作るのに便利。記事公開するだけのSPAなんぞいらねーよね。ってとき便利

でもnginx で出来ない。→ 置換すればできるよ。

URIディレクトリを修正する方法の例

プロキシリクエストの結果を書き換えられるので、それを仕込んで見る。

応答はsub_filter で置換できる。

   location ~/blog/(.*) {

      # rewrite ^ $1 break;
     proxy_set_header Host $host;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header X-Forwarded-Proto $scheme;

     set $nocache 0;

     if ($arg_filter_distance = "") {
         set $nocache 1;
     }
     proxy_cache_bypass $nocache;
     proxy_no_cache $nocache;


     proxy_pass http://127.0.0.1:1234/$1;


     sub_filter '/static'  "${uri}static";
     sub_filter '/task'  "${uri}task/";
     sub_filter_once off;
   }

ポイント

ここで、proxy 取得したHTMLの「コンテンツを書き換え(sub_filter)」ている。

     sub_filter '/static'  "${uri}static";
     sub_filter '/task'  "${uri}task/";

ただし、JSにかかれてJSでLocationを管理されると手出しができないので注意。

HTML ファイル以外を書き換えたい。

「sub_filter 」はContent-Typeを見ていて、Content-Typeがtext/html 以外を編集しない。

octet-stream や video を書き換えても徒労に終わるからだ。ただm3u8やjs など文字列は書き換えても良い。

その場合は、Content-Typeを明示する

sub_filter_types application/x-mpegURL;      
## 複数書くときはスペースで列挙
sub_filter_types text/html application/x-mpegURL; 
## ワイルドカードも
sub_filter_types text/* application/*; 

このように、sub_filter_types を使って subfilter が動作するファイルを追加する必要がある。

複数のタイプの書き方やワイルドカードの例については、本家のドキュメントに具体的な指示がないので、たぶんnginx 一般の書き方なんだろう。

どういうときに使えるのか

サブディレクトリに非対応なWebアプリケーションを無理やりサブディレクトリで展開するのに便利。

サブディレクトリにしたほうが便利なアプリケーションがある。たとえば、複数のブログとか。たとえば、JiraとConfulenceとか。

2023-09-28

sub_filter で検索したときに、でてこなかったので書き換え