20210911のLinuxに関する記事は8件です。

GUI有効なLinux環境で、複数のNICを有効にする

 タイトル通りなのですが、複数のNIC(ネットワークインターフェイス)が有効なマシンにGUI有効なLinux環境を構成し、NICの状態を確認すると以下のようになったりします。 NICの状態の確認 root@debian11:~# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:cb:4c:49 brd ff:ff:ff:ff:ff:ff inet 192.168.56.112/24 brd 192.168.56.255 scope global dynamic noprefixroute enp0s3 valid_lft 555sec preferred_lft 555sec inet6 fe80::a00:27ff:fecb:4c49/64 scope link noprefixroute valid_lft forever preferred_lft forever 3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:72:0c:a0 brd ff:ff:ff:ff:ff:ff → enp0s3、enp0s8の2つのNICが認識されている root@debian11:~# nmcli connection show NAME UUID TYPE DEVICE Wired connection 1 a0195015-9413-4d5c-ba5f-56d2eb6850fe ethernet enp0s3 → nmcliでコネクション情報を表示すると、片方しか表示されない 認識されていない方のNICについては、コネクション情報を追加します。 コネクション情報の追加 root@debian11:~# nmcli connection add type ethernet ifname enp0s8 con-name enp0s8 接続 'enp0s8' (b653076d-48c4-4b2f-a49c-5d7238a81f7a) が正常に追加されました。 → コネクション情報が追加される root@debian11:~# nmcli connection show NAME UUID TYPE DEVICE enp0s8 b653076d-48c4-4b2f-a49c-5d7238a81f7a ethernet enp0s8 Wired connection 1 a0195015-9413-4d5c-ba5f-56d2eb6850fe ethernet enp0s3 → enp0s8が追加されていることを確認 構文の説明:コネクション情報の追加 nmcli connection add type ネットワークの種類 ifname NIC名 con-name コネクション名  これで複数のNICが利用できるようになるのですが、さらに既定で認識したコネクションの名前(Wired connection 1)をNICの名前と同じになるように変更します コネクション名の変更 root@debian11:~# nmcli connection modify 'Wired connection 1' connection.id enp0s3 → コネクション名Wired connection 1をenp0s3に変更 root@debian11:~# nmcli connection show NAME UUID TYPE DEVICE enp0s8 b653076d-48c4-4b2f-a49c-5d7238a81f7a ethernet enp0s8 enp0s3 a0195015-9413-4d5c-ba5f-56d2eb6850fe ethernet enp0s3 構文の説明:コネクション名の変更 nmcli connection modify 既存のコネクション名 connection.id 変更後のコネクション名 ※コネクション名にスペースを含む場合、クォーテーションで囲んで指定  これでどちらのNICもnmcliコマンドで制御できるようになり、かつ「nmcli connection modify NIC名...」で設定内容を変更できるようになります。  例えば、enp0s3に割り当てられるIPv4アドレスを固定のものにするには、以下の構文を実行します。 IPv4アドレスを固定のものに割り当て nmcli connection modify enp0s3 ipv4.address '192.168.56.22/24' nmcli connection modify enp0s3 ipv4.method 'manual'
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

教養としての5GC(free5gc+UERANSIMで学ぶ5Gコアネットワーク)その5

前回まではueransimをinstallして疑似5G基地局、疑似UEから5GCにRegistrationを試みてみました。 前回は失敗してしまったので今回はUEを5GC側に登録します。 1. free5gcのwebconsoleを使ってみる free5gcには加入者データやUEの状態遷移を確認できるGUI(webconsole)がついています。 free5gc VM上で以下の通り起動します。ポート5000番でWeb Serverが起動します。 q14537@free5gc:~/free5gc/webconsole/bin$ ls webconsole q14537@free5gc:~/free5gc/webconsole/bin$ ./webconsole Host PC上のブラウザからアクセスしてみます。今回の環境では192.168.56.103:5000です。 そうすると以下のようなログイン画面が出てきます。 username:admin/password:free5gcでログインしてみます。 左のSubscriberのメニュをクリックするとNew Subscriberが登録できますので、ここで前回のueransimで使っていたUE情報を登録します。基本的にueransimのfree5gc-ue.yamlの内容が既に入っているのですがPLMINDを変えたのでそこだけ44020に変更します。 一番下のSubmitを押すと加入者情報が登録されます。 2. 再度ueransimから電源ONを試してみる。 今回は以下の様に成功しました。 UERANSIM v3.2.3 [2021-09-11 09:37:44.840] [rrc] [debug] New signal detected for cell[1], total [1] cells in coverage [2021-09-11 09:37:44.840] [nas] [info] UE switches to state [MM-DEREGISTERED/PLMN-SEARCH] [2021-09-11 09:37:44.841] [nas] [info] Selected plmn[440/20] [2021-09-11 09:37:44.841] [rrc] [info] Selected cell plmn[440/20] tac[1] category[SUITABLE] [2021-09-11 09:37:44.841] [nas] [info] UE switches to state [MM-DEREGISTERED/PS] [2021-09-11 09:37:44.841] [nas] [info] UE switches to state [MM-DEREGISTERED/NORMAL-SERVICE] [2021-09-11 09:37:44.841] [nas] [debug] Initial registration required due to [MM-DEREG-NORMAL-SERVICE] [2021-09-11 09:37:44.844] [nas] [debug] UAC access attempt is allowed for identity[0], category[MO_sig] [2021-09-11 09:37:44.844] [nas] [debug] Sending Initial Registration [2021-09-11 09:37:44.845] [rrc] [debug] Sending RRC Setup Request [2021-09-11 09:37:44.845] [rrc] [info] RRC connection established [2021-09-11 09:37:44.845] [rrc] [info] UE switches to state [RRC-CONNECTED] [2021-09-11 09:37:44.845] [nas] [info] UE switches to state [MM-REGISTER-INITIATED] [2021-09-11 09:37:44.845] [nas] [info] UE switches to state [CM-CONNECTED] [2021-09-11 09:37:44.865] [nas] [debug] Authentication Request received [2021-09-11 09:37:44.873] [nas] [debug] Security Mode Command received [2021-09-11 09:37:44.873] [nas] [debug] Selected integrity[2] ciphering[0] [2021-09-11 09:37:44.945] [nas] [debug] Registration accept received [2021-09-11 09:37:44.945] [nas] [info] UE switches to state [MM-REGISTERED/NORMAL-SERVICE] [2021-09-11 09:37:44.945] [nas] [debug] Sending Registration Complete [2021-09-11 09:37:44.946] [nas] [info] Initial Registration is successful [2021-09-11 09:37:44.946] [nas] [debug] Sending PDU Session Establishment Request [2021-09-11 09:37:44.946] [nas] [debug] UAC access attempt is allowed for identity[0], category[MO_sig] [2021-09-11 09:37:45.192] [nas] [debug] PDU Session Establishment Accept received [2021-09-11 09:37:45.192] [nas] [warning] SM cause received in PduSessionEstablishmentAccept [PDU_SESSION_TYPE_IPV4_ONLY_ALLOWED] [2021-09-11 09:37:45.200] [nas] [info] PDU Session establishment is successful PSI[1] [2021-09-11 09:37:45.207] [app] [info] Connection setup for PDU session[1] is successful, TUN interface[uesimtun0, 60.60.0.1] is up. 前回はUDRでそんなUE情報知らないと怒られましたが、今回はUDR(127.0.0.4)はちゃんと返事をしています。 ueransim上のVMでは以下の様にuesimtun0と言う名前でGTPトンネル用のインターフェイスが追加されています。 uesimtun0: flags=369<UP,POINTOPOINT,NOTRAILERS,RUNNING,PROMISC> mtu 1400 inet 60.60.0.1 netmask 255.255.255.255 destination 60.60.0.1 inet6 fe80::4eb3:fe43:8c48:641d prefixlen 64 scopeid 0x20<link> unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 7 bytes 448 (448.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 このインターフェイスを使ってDN(Data Network、いわゆる外のネットワーク)にpingしてみます。 見事にpingの返信がgoogleから返ってきます。 q14537@ueransim:~$ ping -I uesimtun0 www.google.com PING www.google.com (142.250.199.100) from 60.60.0.1 uesimtun0: 56(84) bytes of data. 64 bytes from nrt13s52-in-f4.1e100.net (142.250.199.100): icmp_seq=1 ttl=115 time=5.22 ms 64 bytes from nrt13s52-in-f4.1e100.net (142.250.199.100): icmp_seq=2 ttl=115 time=5.70 ms 64 bytes from nrt13s52-in-f4.1e100.net (142.250.199.100): icmp_seq=3 ttl=115 time=5.16 ms Wiresharkで見てもGTPパケットがちゃんと下のレイヤではUERANSIM(192.168.56.102)からfree5gc(192.168.56.103)に流れており、上のGTPレイヤではUEのアドレス(60.60.0.1)からgoogleのアドレス(142.250.199.100)に流れています。 webconsoleで5GCのNFの状態が見れますので見てみましょう。 AMFの保持している情報。UE情報とかUEに割り振っているGUTIとか見えます。 SMFの保持している情報。DNNとかPDUAddress(UEに割り振っているアドレス)等が見えます。 3. UERANSIMのCLIを使ってみる ueransim側でもnr-cliというCLI Toolで色々状態が見えますので見てみましょう。 まずはgNodeBの情報。gNodeBが接続されているAMFの情報やこのgNodeBに接続されているUEの数等が見えます。 q14537@ueransim:~/UERANSIM/build$ ./nr-cli -d UERANSIM-gnb-440-20-1 imsi-440200000000003 q14537@ueransim:~/UERANSIM/build$ ./nr-cli UERANSIM-gnb-440-20-1 -------------------------------------------------------------------------------------------- $ commands info | Show some information about the gNB status | Show some status information about the gNB amf-list | List all AMFs associated with the gNB amf-info | Show some status information about the given AMF ue-list | List all UEs associated with the gNB ue-count | Print the total number of UEs connected the this gNB ue-release | Request a UE context release for the given UE -------------------------------------------------------------------------------------------- $ info name: UERANSIM-gnb-440-20-1 nci: 16 plmn: 440/20 tac: 1 nssai: - sst: 0x01 sd: 0x010203 ngap-ip: 192.168.56.102 gtp-ip: 192.168.56.102 paging-drx: v128 ignore-sctp-id: true -------------------------------------------------------------------------------------------- $ status is-ngap-up: true -------------------------------------------------------------------------------------------- $ amf-list - id: 2 -------------------------------------------------------------------------------------------- $ amf-info 2 id: 2 name: AMF address: 192.168.56.103:38412 state: CONNECTED capacity: 255 association: id: 2 rx-num: 3 tx-num: 5 served-guami: - guami: plmn: 440/20 region-id: 202 set-id: 1016 pointer: 0 backup-amf: served-plmn: - plmn: 440/20 nssai: - sst: 0x01 sd: 0x010203 - sst: 0x01 sd: 0x112233 -------------------------------------------------------------------------------------------- $ ue-list - ue-id: 1 ran-ngap-id: 1 amf-ngap-id: 1 -------------------------------------------------------------------------------------------- $ ue-count 1 -------------------------------------------------------------------------------------------- そしてUEの情報。UE側でも、振られているアドレス、QoSの値などが見えます。 q14537@ueransim:~/UERANSIM/build$ ./nr-cli imsi-440200000000003 -------------------------------------------------------------------------------------------- $ commands info | Show some information about the UE status | Show some status information about the UE timers | Dump current status of the timers in the UE rls-state | Show status information about RLS coverage | Dump available cells and PLMNs in the coverage ps-establish | Trigger a PDU session establishment procedure ps-list | List all PDU sessions ps-release | Trigger a PDU session release procedure ps-release-all | Trigger PDU session release procedures for all active sessions deregister | Perform a de-registration by the UE -------------------------------------------------------------------------------------------- $ info supi: imsi-440200000000003 hplmn: 440/20 imei: 356938035643803 imeisv: 4370816125816151 ecall-only: false uac-aic: mps: false mcs: false uac-acc: normal-class: 0 class-11: false class-12: false class-13: false class-14: false class-15: false is-high-priority: false -------------------------------------------------------------------------------------------- $ status cm-state: CM-CONNECTED rm-state: RM-REGISTERED mm-state: MM-REGISTERED/NORMAL-SERVICE 5u-state: 5U1-UPDATED sim-inserted: true selected-plmn: 440/20 current-cell: 1 current-plmn: 440/20 current-tac: 1 last-tai: PLMN[440/20] TAC[1] stored-suci: no-identity stored-guti: plmn: 440/20 amf-region-id: 0xca amf-set-id: 1016 amf-pointer: 0 tmsi: 0x00000001 has-emergency: false -------------------------------------------------------------------------------------------- $ coverage [1]: signal: -1 dBm (Excellent) mib: barred: false intra-freq-reselection: allowed sib1: nr-cell-id: 0000000000000010 plmn: 440/20 tac: 1 operator-reserved: false -------------------------------------------------------------------------------------------- $ ps-list PDU Session1: state: PS-ACTIVE session-type: IPv4 apn: internet s-nssai: sst: 0x01 sd: 0x010203 emergency: false address: 60.60.0.1 ambr: up[200Mb/s] down[100Mb/s] data-pending: false -------------------------------------------------------------------------------------------- 3.1 State Machine このUEのstatusコマンドで見える以下の情報が、それぞれConnetion Management, Registration Management, Mobility Management?で5GC側とUEがメッセージをやりとりし状態遷移をします。CM-Connected, RM-Registredの状態でないとパケットが送信出来ないとかルールがあります。 cm-state: CM-CONNECTED rm-state: RM-REGISTERED mm-state: MM-REGISTERED/NORMAL-SERVICE 引用元:3GPP TS23.501 4. mongodbにストアされているデータを見てみる webconsole経由で加入者データを登録しましたがバックエンドはMongoDBを使っている様です。free5gc内ではUDRが実際にMongoDBを読み書きしているのですね。 直接MongoDBにアクセスして情報を見る事もできます。 q14537@free5gc:~$ mongo MongoDB shell version v3.6.8 connecting to: mongodb://127.0.0.1:27017 Implicit session: session { "id" : UUID("7f01f3e7-d3da-4440-a5b1-2bd756cf4556") } MongoDB server version: 3.6.8 > show dbs admin 0.000GB config 0.000GB free5gc 0.001GB local 0.000GB > use free5gc switched to db free5gc > show collections NfProfile policyData.ues.amData policyData.ues.smData subscriptionData.authenticationData.authenticationStatus subscriptionData.authenticationData.authenticationSubscription subscriptionData.contextData.amf3gppAccess subscriptionData.provisionedData.amData subscriptionData.provisionedData.smData subscriptionData.provisionedData.smfSelectionSubscriptionData urilist > db.subscriptionData.provisionedData.amData.find() { "_id" : ObjectId("613b76748e1b2adeb79ecf7b"), "gpsis" : [ "msisdn-0900000000" ], "subscribedUeAmbr" : { "uplink" : "1 Gbps", "downlink" : "2 Gbps" }, "nssai" : { "defaultSingleNssais" : [ { "sst" : 1, "sd" : "010203" }, { "sst" : 1, "sd" : "112233" } ] }, "ueId" : "imsi-440200000000003", "servingPlmnId" : "44020" } { "_id" : ObjectId("613ca8532195f9a233697ac5"), "gpsis" : [ "msisdn-0900000000" ], "subscribedUeAmbr" : { "uplink" : "1 Gbps", "downlink" : "2 Gbps" }, "nssai" : { "defaultSingleNssais" : [ { "sd" : "010203", "sst" : 1 }, { "sst" : 1, "sd" : "112233" } ] }, "ueId" : "imsi-440200000000004", "servingPlmnId" : "44020" } db.subscriptionData.provisionedData.amData.find()で見てみると先ほどwebconsoleで登録したimsi-440200000000003が入っている事が分かります。 5. Deregistationしてみる UERANSIMのCLIから電源OFFのオプションでDeregistratonしてみます。 これでネットワークからこのUEはいなくなった事になります。 (ちなみに電源OFF以外のオプションはうまく動作しませんでした。なんでだろ。。) q14537@ueransim:~/UERANSIM/build$ ./nr-cli imsi-440200000000003 -------------------------------------------------------------------------------------------- $ deregister switch-off De-registration procedure triggered. UE device will be switched off. -------------------------------------------------------------------------------------------- UERANSIMのログでも確認できます。 [2021-09-11 13:58:26.000] [nas] [debug] De-registration required due to [SWITCH-OFF] [2021-09-11 13:58:26.011] [nas] [debug] Starting de-registration procedure due to [SWITCH-OFF] [2021-09-11 13:58:26.011] [nas] [debug] Performing local release of PDU session[1] [2021-09-11 13:58:26.012] [nas] [info] UE switches to state [MM-DEREGISTER-INITIATED] [2021-09-11 13:58:26.017] [rrc] [debug] RRC Release received [2021-09-11 13:58:26.017] [nas] [info] UE switches to state [CM-IDLE] [2021-09-11 13:58:26.526] [app] [info] UE device is switching off Wiresharkでも見てみます。Deregistration Requestが送られています。 6. 最後に 教養としての5GCの連載は今回で終わりです。あまり5GCならではの機能、例えばネットワークスライシング、ユニークなNFであるNEF(free5gcでは未実装)等の説明はしませんでしたが、UERANSIM+free5gcのインテグをする事でかなり遊べる物だとは感じて頂けたかなと思います。UPFもMECの為に多段構成に出来たりするみたいので挑戦しても良いかもです。 オープンソース物でここまで色々出来るとは正直思っていなかったので思わず記事にしてみました。まだまだ動作に不安定な部分がありますが、PoCや学習目的で気軽に使うには十分なのではと思います。実際の5GCは当然5-6000万人の加入者を支えないといけないので、スケールも違うし、事業者が商用運用していく上での耐障害性や統計データなどのいわゆるFCAPS機能は実装されていないので、商用利用には難しいかな思います。 しかしながらオープンソースなので自分でもっと色々機能を追加してみる事も簡単にできるので是非NEFあたりを実装してみては如何でしょうか。 7. 参考にしたサイト
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

make && make install 実行中に file cannot create directory: /usr/local/lib/pkgconfig. Maybe need administrative privileges.

概要 cmakeを使ってライブラリをbuildしていた際に パッケージの説明に従ってmake && make installを実行したら file cannot create directory: /usr/local/lib/pkgconfig. Maybe need administrative privileges. と怒られた。 administrative って書いてあるのでsidoつければいいかなと思ったので sudo make && make installに変えても同じエラーに、、 結論 &&使っているので両方のコマンドにsudoつけないとダメだった。。 sudo make && sudo make install これで解決。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[ Gitlab Runner ] CI / CD パイプラインを構築する①(CI編)

はじめに 最近の開発現場ではもはや当たり前のものとして整備されつつある、 CI/CDパイプライン ですが、私が参画した開発現場では導入されていませんでした。 CI/CDパイプラインは導入すると様々なメリットがあるので、導入した方が良いと思い、自ら社内の開発現場への導入を進めました。 CI/CDとは 簡単に説明するとアプリケーションのビルド、テスト、デプロイを自動で行い、開発の生産性を向上させるための開発の手法です。 CIのメリット Linterを実行することで規定されたルールに則っていないソースコードを事前に検知できる。 Formatterを実行することで、同一のリポジトリ内においてソースコードのフォーマットを強制的に統一することができる。 デバッグコードを事前に検知し、本番環境に不要なデバッグコードがリリースされることを未然に防ぐことができる。 アプリケーションのビルドが問題なく行われるかどうかのチェックを、本番環境へのリリース前に自動で行うことができる。 補足として、最後にあげたメリットに関しては本番環境をコンテナ基盤で運用している場合に教授できるメリットですがCIのメリットとして挙げられる代表的なものの一つとなるかなと思います。 リポジトリ内に本番環境用の Dockerfile を含めておいて、CIの処理の中に自動でビルドされるようにしておけば、もしビルドが失敗した際に事前に検知できるのかなと思います。 CDのメリット 本番環境へのリリース作業において社内の特定の人物しか把握していないというような状況を防ぐことができる。 リリース作業を自動化することで開発者の作業ミスを防ぐことができる。 アプリケーションのダウンタイムをゼロにすることができる。 CI/CD導入におけるデメリット 既存の開発現場にCI/CDの仕組みが整備されていない場合、チームの開発者にCI/CDの導入を前提とする開発スタイルに馴染ませる必要がある。 CI/CDパイプラインをメンテナンスする開発者が必要になる。 CI/CDの仕組みに関して、チームの開発者にキャッチアップを促す必要がある。 使用したCIツールとCIを実行する環境 使用しているCIツールは、gitlabでCIを行う際のデファクトスタンダードとなっている、 Gitlab Runner を使用しています。 クラウド上にCI専用のサーバー(CentOS7)を構築して、サーバー上に Gitlab Runner をインストールしてCI環境を整備しています。 ※CentOS7に Gitlab Runnerインストールする参考資料 こちらの記事に、gitlab上でCIを行う際の設定について解説されているので参考にしてください。 実際に使用しているCIスクリプト こちらのリポジトリにもまとめていますので、参考にしてください。 .gitlab-ci.yml image: php:7.4-fpm cache: key: one-key-to-rule-them-all paths: - vendor/ - node_modules/ before_script: - apt-get update - apt-get install -y git libzip-dev libpng-dev - docker-php-ext-install zip - curl --silent --show-error https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer - mkdir ~/.ssh - chmod 700 ~/.ssh - echo "$KNOWN_HOSTS" >> ~/.ssh/known_hosts - echo "$SSH_KEY" >> ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - eval "$(ssh-agent)" - ssh-add ~/.ssh/id_rsa - ssh-add -l - echo "$SSH_CONFIG" >> ~/.ssh/config - git remote set-url --push origin ssh://git@255.255.255.255:65535/web/sample_project.git - git remote -v - git remote update - git config --global user.name gitlab_runner - git config --global user.email gitlab.runner@example.com - if [[ `git branch | grep $CI_COMMIT_REF_NAME` ]]; then - git branch -D $CI_COMMIT_REF_NAME - fi - if [[ ! `git branch | grep $CI_COMMIT_REF_NAME` ]]; then - git branch $CI_COMMIT_REF_NAME origin/$CI_COMMIT_REF_NAME - fi - git branch stages: - build - formatter formatter: stage: formatter script: - git checkout $CI_COMMIT_REF_NAME - apt-get install -y lsof nodejs npm - npm install - pecl install mongodb - docker-php-ext-enable mongodb - git checkout $CI_COMMIT_REF_NAME - ssh -t -t web_app_db -f -N - lsof -i - composer install - cp .env.example .env - echo "$ENV_FILE" >> .env - php artisan key:generate - vendor/bin/phpunit tests/Feature/api_test.php - vendor/bin/phpunit tests/Feature/Api - SYNTAX_CHECK=0 - for FILE in `git diff --name-only origin/master | grep -E '*php'` ; do - echo $FILE - ./vendor/bin/php-cs-fixer fix $FILE - echo 'PHPMDで未使用変数などのチェック' - if ! ./vendor/bin/phpmd $FILE text ruleset.xml; then - SYNTAX_CHECK=1 - fi - done - IS_ERROR=0 - for FILE in `git diff --name-only origin/master | grep -E '*js'` ; do - if [ $FILE = '.eslintrc.json' ]; then - echo $FILE - echo "skip check" - continue - fi - if [ $FILE = 'composer.json' ]; then - echo $FILE - echo "skip check" - continue - fi - if [ $FILE = 'package-lock.json' ]; then - echo $FILE - echo "skip check" - continue - fi - if [ $FILE = 'package.json' ]; then - echo $FILE - echo "skip check" - continue - fi - if [ $FILE = WebGL_Release.framework.js ]; then - echo $FILE - echo "skip check" - continue - fi - if [[ -n `./node_modules/.bin/eslint --fix $FILE` ]]; then - ./node_modules/.bin/eslint --fix $FILE - IS_ERROR=1 - fi - done - git add -A - git status - if [[ -n "`git status --porcelain`" ]];then - git commit -m '[ci skip]Push by GitLab runner' - git push origin $CI_COMMIT_REF_NAME - fi - IS_ERROR_LOG_REMAIN_ERROR=0 - for FILE in `git diff --name-only origin/master | grep -E '*php'`; do - echo $FILE - if [[ -n `git grep error_log -- $FILE` ]]; then - echo -e "\e[31;43m デバッグコードが残っている可能性があります。'\n'削除してください \e[m" - IS_ERROR_LOG_REMAIN_ERROR=1 - else - IS_ERROR_LOG_REMAIN_ERROR=0 - fi - done - if [ $SYNTAX_CHECK -eq 0 -a $IS_ERROR_LOG_REMAIN_ERROR -eq 0 ]; then - exit 0 - else - echo -e "\e[31;43m 修正を行った上で再度コミットしてください \e[m" - exit 1 - fi except: - master CI運用時に発生した事象 今まで問題なく動いていたCIが、ある時を境に全プロジェクトで一斉にこけるという事態が発生しました。 その際に発生した問題と、実際に解決を図ったプロセスについて解決したいと思います。 発生した問題 CIの処理実行時に、以下の処理の部分でCIがこけてしまっていますね。 $ docker-php-ext-install zip Configuring for: PHP Api Version: 20190902 Zend Module Api No: 20190902 Zend Extension Api No: 320190902 ls: cannot access '.': Operation not permitted configure: error: working directory cannot be determined Cleaning up file based variables ERROR: Job failed: exit code 1 解決手順 1. ls: cannot access '.': Operation not permitted gitlab でgoogle検索 見出しのキーワードで検索すると、こんな記事が出てきました。 https://webclass.jp/blog/2021/07/01/docker%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E5%86%85%E3%81%A7-make-bin-sh-operation-not-permitted/ 何か、dockerのversionが関係している可能性があるようです。 2. CIサーバー上のDockerのversionを確認する。 サーバーにインストールされているdockerのバージョンを確認してみましょう。 サーバーにインストールされているdockerのversion [root@gitlab-runner ~]# docker -v Docker version 20.10.3, build 48d30b5 なるほど。 サーバーにインストールされているバージョンがわかったところで現在のdocker最新版を確認します。 ※docker最新バージョンを確認 https://openstandia.jp/oss_info/docker/version/ 3. インストール済みのdockerをremove 既存のdockerを一旦アンインストールします。 yum remove docker-ce docker-selinux docker-engine-selinux 4. docker最新版をインストール sudo yum install docker-ce -y 4. docker再起動 systemctl start docker ※dockerを最新版にするための参考資料 https://qiita.com/okcoder/items/e91f1e339c114e0be129 以上を行った後に、再度CIを走らせると処理が止まらずに無事にCIを実行することができました。 最後に gitlabでCIを行うとすると自前でサーバーを用意して、運用も自分たちで行う必要があるため、少し大変な面もありますが、安定して運用が行えるように環境を整備していきたいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

REST API のレスポンス速度を改善するために行なった設計の上で大切なこと

はじめに 社内のプロジェクトで、大量のデータをjsonで返すAPIを実装した際に、レスポンス速度が遅くなりすぎるという課題が発生したことがありました。 この、課題を解決する過程で、開発者がWebサービスを実装する上で意識した方が良い点をいくつか学んだので記事にまとめたいと思います。 for 分のネストを浅くする まず、以下のソースコードを見てください。 api.php $all_datas = $this->model->find($query); foreach($all_datas as $data){ foreach($data['data'] as $value_type => $data_by_type){ foreach($data_by_type as $timestamp => $val){ $response_array[$timestamp] = $val; } } } このようにfor分のネストが深くなると、OSのメモリ上にデータを格納した状態が長く続き、サーバーに大きな負荷がかかってしまいます。 また、ループが何十にも回るせいで非常に大量の回数が回ることになり、このループを抜けるのに非常に時間がかかってしまいます。 対策 for文のネストは極力浅くする必要がありますし、連想配列を使用してデータを作成する際にも、for文のネストが深くならないようにデータ構造を設計してやる必要があります。 場合によっては、DBの設計についても考慮して、API側でデータを扱う際に、使用しやすい形式でDB保存を行う必要もあるかもしれません。 DBに投げるクエリを工夫する 以下のソースコードを見てください。 foreach($user_data as $user_info){ $user_id = $user_info['id']; $data = $this->model->find($user_id); } for分の中で何回もDBへの検索を行なっていると、DBへの検索処理を行うたびに時間がロスしてしまいます。 また、DBへの負荷もかかる。 対処法 改善したソースコード foreach($user_data as $user_info){ $user_id = $user_info['id']; $user_id_list[] = $user_id; } $data = $this->model->find($user_id_list); 1回のクエリでデータをまるっと取得できるようにしてやると良いかなと思います。 未使用変数及び無駄な変数は減らす 未使用変数や無駄な変数が残っていると、以下のような問題点があるかなと思います。 * ソースコードの可読性が落ちる。 * メモリ上に無駄なメモリ領域が確保されてしまう。 PHP関数内の変数について PHPでは関数内で定義された変数は、関数の処理終了時にメモリが開放されるようです。 for文のネストが深く、かつループ分の中で変数に値を代入する際には、適宜変数を初期化してやることで意図しない値が代入されることを防いだり、余分なメモリ領域を確保したままループが回り続けるという現象も防げるのかなと思います。 対処法 この辺りはLinterのルールの中に、未使用変数の残存をチェックするルールを追加して、チーム内で共通で使用するようにすれば、解消できるかなと思います。 また、CI上でLinterを実行するようにしておけば、GithubやGitlab上でコードレビューを行う際に事前にチェックができるかなと思います。 jsonのsizeを軽くする json内部のデータを見直す jsonのデータの中に不要なデータが多く含まれていると、サーバーからクライアントにjsonを送信する際に無駄な時間がかかってしまいます。 大量のデータを扱っている際には、無駄なデータが含まれているせいで数MB単位でデータが肥大化してしまうこともあるので注意が必要ですね。 nginxでデータを圧縮する nginxの設定でjsonデータを圧縮することでデータを軽くすることができます。 サーバー側の対策 swapを使用する swap領域を確保してやることで、物理メモリが圧迫された時にバッファを持たせることができます。 ただし、swap領域を確保する際にサーバーのハードディスクを必要とするため、容量に余裕を持たせておく必要があります。 バッチ処理を作成する あらかじめデータを整形したり、計算しておくことで、API内部の処理を減らすことができるようになり、レスポンス速度が改善できる可能性があります。 もし、仮にバッチ処理を挟まずに、webアプリ側のmodel等で処理を実行させると、ネストの深いfor分が複数あった場合には、サーバーに負荷がかかりますし、APIのレスポンス速度も著しく悪化してしまいます。 Redisの使用を検討する redisを使用してキャッシュを効かせることでDBへのアクセスを減らすことが期待できます。 ただし、redisを使用する際にはキャッシュがOSのメモリ上に保存されるため、サーバーのメモリについても考慮する必要があります。 laravelではデフォルトでSession及びCacheの保存先がstorageディレクトリ内に保存されるため、長期間運用をしているとstorageディレクトリが肥大化し、OS上のストレージを圧迫してしまいます。 サービスのアクセス数が少ないうちは大きな問題にならないかもしれませんが、実運用を考えると早めにRedisを使用する必要があるでしょう。 redisを導入する際にはこちらの記事を参考にしてください。 https://qiita.com/takuyanagai0213/items/2e4fe3fafcb99cb1a10e
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Python】GooglePhotosAPIで写真・動画のバックアップを取得する方法

はじめに 去年娘が生まれてからスマホで写真や動画を取る頻度がとても増えました。 私も妻もAndroidユーザーなので、自動でGoogle Photoに同期するようにしていて、非常に便利なのですが容量が15GBまでの制限があり、バックアップを取ってから削除していくというのを手動で行っておりました。 何とかならないものかと思い、自動で自宅のNASに写真や動画をバックアップするスクリプトを作りました。 tl;dr AndoridのGooglePhotoへの自動アップロードしておく pythonでGoogleのAPIををつかって写真と動画を取得するスクリプトを作成 ローカルサーバーのcronに仕込んで日次実行させる サーバーへの定義とスクリプトのデプロイはAnsible スクリプトのコードはこちら 目次 環境と構成 GCPでAPI有効化とOAuth認証設定 pythonでPhoto Library APIを実行 ReadyNASでのNFS有効化 ローカルサーバーへのデプロイ 結果 環境と構成 HW 開発PC Microsoft Windows 10 Pro (build 19043) Mac Book Pro BigSur(version 11.5.2) 本番環境 NUC (Intel NUC BOXNUC6CAYH) CentOS Linux release 7.9.2009 (Core) NAS (NETGEAR ReadyNAS 214 RN214) RAID 5(3D+1P: 6Gb/s 256MB 5400rpm 4TB*4) 言語 python 3.6.8 google-api-core (2.0.1) google-api-python-client (2.20.0) google-auth (2.0.2) google-auth-httplib2 (0.1.0) google-auth-oauthlib (0.4.6) python-dateutil (2.8.2) その他 VSCode(別に他のIDEでもいいです) Ansible(Dockerイメージとして構築。なのでWindows/MacにはDockerの実行環境が必要) 構成 ざっくりとした構成は以下の通りです。 GCPのコンソールでAPIの設定をしておく ローカルPCからNUCに対してAnsibleで定義更新とGitHubからのクローンを行う 初回実行は対象のユーザーのPC(AndroidのGoogleアカウントと同じユーザーでログインしているPC)でNUCにssh経由で行い、認証を通しておく cronでキックされたらPhoto Libraryで写真と動画のリストを取得し、新しい写真や動画があればdownloadしてNASに保存する API有効化とOAuth認証の設定 Photo Library APIの有効化 Google API Consoleにアクセス プロジェクトを作成していない場合は新規でプロジェクトを作成しておく。今回はgoogle-photo-backupとしました。 上部の検索バーでPhoto Libraryを入力してPhoto Library APIをクリックする。 Photo Library APIの有効にするボタンをクリックし、有効化しておく。 OAuth 2.0 クライアントIDの作成 画面左上のメニューからAPIとサービスを選択して、認証情報をクリックする。 アプリ名、ユーザーサポートメール、メールアドレスを入力し、保存して次へをクリックする。 アプリ名に「-」などが入っていると、エラーが発生します。 メニューからOAuth同意画面を選択し、UserTypeを外部にして作成をクリックする。 スコープは省略して大丈夫です。 画面上部の認証情報を作成をクリックし、OAuth クライアント IDをクリックする。 アプリケーションの種類でデスクトップアプリを選択して作成をクリックする。 作成されたOAuth 2.0 クライアント IDの右側にあるダウンロードボタンをクリックし、jsonファイルをダウンロードする。 pythonでPhoto Library APIを実行 先ほどダウンロードしたclient_secret~~.jsonをclient_secret.jsonにリネームして、スクリプトと同じフォルダに配置しておきます。 初回はこちらを使って認証を行いcredential.jsonを生成し、次回以降はcredential.jsonを用いて認証します。 こちらを参考にしました。 SCOPES = ['https://www.googleapis.com/auth/photoslibrary'] API_SERVICE_NAME = 'photoslibrary' API_VERSION = 'v1' CLIENT_SECRET_FILE = 'client_secret.json' CREDENTIAL_FILE = 'credential.json' def getCredentials(): """ API接続時にクレデンシャルを取得する。 初回はclient_secret.jsonをもとに認証を行い ユーザー操作の後credential.jsonを生成する 次回以降はcredential.jsonをもとに認証を行う Returns ---------- credential : Any クレデンシャル情報 """ if os.path.exists(CREDENTIAL_FILE): with open(CREDENTIAL_FILE) as f_credential_r: credentials_json = json.loads(f_credential_r.read()) credentials = google.oauth2.credentials.Credentials( credentials_json['token'], refresh_token=credentials_json['_refresh_token'], token_uri=credentials_json['_token_uri'], client_id=credentials_json['_client_id'], client_secret=credentials_json['_client_secret'] ) else: flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file( CLIENT_SECRET_FILE, scopes=SCOPES) credentials = flow.run_console() with open(CREDENTIAL_FILE, mode='w') as f_credential_w: f_credential_w.write(json.dumps( vars(credentials), default=support_datetime_default, sort_keys=True)) return credentials def main(): # クレデンシャルを取得 credentials = getCredentials() service = build( API_SERVICE_NAME, API_VERSION, credentials=credentials, static_discovery=False ) このserviceを使ってAPIにアクセスします。 query bodyを渡して、mediaItems = service.mediaItems().search(body=queryBody).execute()のようにアクセスします。 後々ダウンロードするときに、写真と動画を分ける必要があるので、mediaMetadataの中にphotoがあるかないかで判定しています。 def getMediaIds(service): """ APIに接続しMediaItemを取得する Parameters ---------- service : int credentialsから生成したAPI接続用のservice Returns ---------- photos : list id,filename,url videos : list id,filename,url """ photos = [] videos = [] now = datetime.now() logger.debug('datetime.now() : %s', now) nextPageTokenMediaItems = '' while True: queryBody = getQueryBody(nextPageTokenMediaItems, now, QUERY_FILTER) mediaItems = service.mediaItems().search(body=queryBody).execute() logger.debug('mediaItems length = %s', len(mediaItems)) if len(mediaItems) == 0: logger.info('mediaItems nothing') break for mediaItem in mediaItems['mediaItems']: photo = {} video = {} if 'photo' in mediaItem['mediaMetadata']: photo['id'], photo['filename'], photo['url'] = mediaItem['id'], mediaItem[ 'filename'], mediaItem['baseUrl'] photos.append(photo) else: video['id'], video['filename'], video['url'] = mediaItem['id'], mediaItem[ 'filename'], mediaItem['baseUrl'] videos.append(video) if 'nextPageToken' in mediaItems: nextPageTokenMediaItems = mediaItems['nextPageToken'] else: break logger.debug('photos length = %s', len(photos)) logger.debug('videos length = %s', len(videos)) return photos, videos query bodyにはフィルターをかけて期間を絞ることが出来ます。 日付でフィルターをかけれるようにしています。フィルターがいらないときは、pageSizeとpageTokenのみを渡せば良いです。 body = { 'pageSize': 50, "filters": { "dateFilter": { "ranges": [ { "startDate": { "year": startDate.year, "month": startDate.month, "day": startDate.day }, "endDate": { "year": referenceDate.year, "month": referenceDate.month, "day": referenceDate.day, }, }, ], }, }, 'pageToken': nextPageTokenMediaItems } ReadyNASでのNFS有効化 我が家にはNETGEARのReadyNASがあるので、こいつにため込むことにしました。 RAID 5で実行容量が12TBあるのでクォータを1TBにしてNFSとしてexportしておきます。 やり方はこちら。 ローカルサーバーへのデプロイ 我が家のNUCにはCentOS7をインストールしていて、構成はAnsibleで管理しています。 なので、そのままAnsibleでデプロイまで管理することにしました。 Docker上でAnsible環境を作る方法はこちら。 各種設定 google photo backup用にroleを作成しました。 roleのmain.ymlはこんな感じです main.yml # main.yml - include: install_require_package.yml notify: - OS reboot - Waiting for server to down - Waiting for server to up - include: setup_nfs_mount.yml - include: setup_logrotate.yml - include: deploy_app.yml - include: setup_app_config.yml - include: setup_cron_job.yml nfs、logrotate、cron_jobのところは本質的ではないので、それ以外のアプリデプロイに関わる部分をかいつまんで解説します。 install_require_package.yml まず必要なパッケージをインストールします。python36をyumでいれるだけです。 iusリポジトリを追加しているのがミソです。 install_require_package.yml # Install require package - name: install the ius-release-el7 rpm from a remote repo become: yes yum: name: https://repo.ius.io/ius-release-el7.rpm state: present - name: install_require_package(yum) become: yes yum: name: - python36u - python36u-libs - python36u-devel - python36u-pip state: present - name: install_require_package(pip with shell confirm) become: yes shell: pip3 show {{ item }} register: pip3_check loop: - google-auth - google_auth_oauthlib - google-api-python-client - python-dateutil changed_when: no failed_when: no - name: install_require_package(pip with shell install) become: yes shell: pip3 install {{ item.item }} when: "item.rc != 0" loop: "{{ pip3_check.results }}" Ansibleにはpipモジュールが存在するのですが、公式に書いてある方法でexecutable: pip3.3としてもうまくpip3を使ってくれなかったので、しかたなくshellで入れています。 shellモジュールでも冪等性が担保されるように、install_require_package(pip with shell confirm)でインストールされているかどうかを確認し、install_require_package(pip with shell install)でインストールされていないパッケージのみインストールしています。changed_when: noとfailed_when: noを指定してやることで、ドライランも対応できます。 deploy_app.yml リポジトリをpublicにしているので、特に認証等はせずにただクローンしています。 client_secret.jsonはansibleの実行環境側で用意しておいたものを配布しています。 クローンしたソースをjobの数だけユーザー毎に別フォルダに配置しています。 配置はクローンが行われた時にだけ行います。(後で設定ファイル書き換えたりするので) deploy_app.yml # deploy_app.yml # クローン用ディレクトリの作成 - name: clone directory making become: yes file: path: /opt/remote-repo/ state: directory owner: root group: root mode: 0755 # git clone - name: git clone from github become: yes ansible.builtin.git: repo: https://github.com/tokku5552/google-photo-backup.git dest: /opt/remote-repo/google-photo-backup register: clone_result # client_secret.jsonのファイル配置 - name: distribute client_secret.json become: yes copy: src: ../files/client_secret.json dest: /opt/remote-repo/google-photo-backup/src/client_secret.json backup: yes # アプリケーション用ディレクトリの作成 - name: app distribute directory making become: yes file: path: /opt/job/{{ item }}/bin state: directory owner: root group: root mode: 0755 loop: - userA - userB # srcのdirectory移動 - name : update source become: yes shell: cp -pr /opt/remote-repo/google-photo-backup/src/* /opt/job/{{ item }}/bin loop: - userA - userB when: clone_result.changed setup_app_config.yml pythonのスクリプト側でsettings.pyというファイルで可変設定項目を定義しているのですが、そちらをansibleで変更できるようにしています。 もともとGitHubリポジトリ上のsettings.pyがクローンされてくるので、変更したいところだけ変えるようにしています。 replaceモジュールで書き換えているだけです。 setup_app_config.yml # setup_app_config.yml # settingを強制上書きする場合 - name : update source (if force) become: yes shell: cp -pr /opt/remote-repo/google-photo-backup/src/* /opt/job/{{ item }}/bin loop: - userA - userB when: gpbk_setting_update_force # setting log filename - name: setting log filename become: yes replace: dest: /opt/job/{{ item }}/bin/settings.py regexp: LOG_FILENAME = '/var/log/google_photos_backup.log' replace: LOG_FILENAME = '/var/log/google_photos_backup_{{ item }}.log' loop: - userA - userB # バックアップディレクトリの作成 - name: make backup directory become: yes file: path: /gpbk/{{ item }} state: directory owner: nobody group: nobody mode: 0777 loop: - userA - userB # setting log filename - name: setting backup directory become: yes replace: dest: /opt/job/{{ item }}/bin/settings.py regexp: DESTINATION_DIR = '/gpbk' replace: DESTINATION_DIR = '/gpbk/{{ item }}' loop: - userA - userB # setting query filter - name: setting query filter become: yes replace: dest: /opt/job/{{ item }}/bin/settings.py regexp: QUERY_FILTER = True replace: QUERY_FILTER = {{ gpbk_query_filter }} loop: - userA - userB # setting debug mode - name: setting debug mode become: yes replace: dest: /opt/job/{{ item }}/bin/settings.py regexp: LOGGING_LEVEL = 20 # DEBUG=10,INFO=20 replace: LOGGING_LEVEL = {{ gpbk_log_level }} # DEBUG=10,INFO=20 loop: - userA - userB 各可変項目はgroup_varsで定義しています。 group_vars/nuc.yml gpbk_setting_update_force: False gpbk_log_level: 10 # DEBUG=10,INFO=20 gpbk_query_filter: False 結果 ログの一部 /var/log/google_photos_backup.log 2021-09-10 04:00:31,295 : [DEBUG] [google_photos_backup.py] mediaItems length = 1 2021-09-10 04:00:31,295 : [DEBUG] [google_photos_backup.py] photos length = 939 2021-09-10 04:00:31,295 : [DEBUG] [google_photos_backup.py] videos length = 33 2021-09-10 04:00:31,296 : [INFO] [google_photos_backup.py] end : get media ids 2021-09-10 04:00:31,296 : [INFO] [google_photos_backup.py] start : remove aquired media ids 2021-09-10 04:00:31,298 : [DEBUG] [google_photos_backup.py] loadIdsJson : aquired media list size = 973 2021-09-10 04:00:31,341 : [DEBUG] [google_photos_backup.py] removeAquiredMedia : result list counts = 0 2021-09-10 04:00:31,344 : [DEBUG] [google_photos_backup.py] removeAquiredMedia : result list counts = 0 2021-09-10 04:00:31,345 : [INFO] [google_photos_backup.py] end : remove aquired media ids 2021-09-10 04:00:31,345 : [INFO] [google_photos_backup.py] start : download media 2021-09-10 04:00:31,345 : [INFO] [google_photos_backup.py] download photos 2021-09-10 04:00:31,345 : [INFO] [google_photos_backup.py] 0 media downloads completed 2021-09-10 04:00:31,345 : [INFO] [google_photos_backup.py] download videos 2021-09-10 04:00:31,346 : [INFO] [google_photos_backup.py] 0 media downloads completed 2021-09-10 04:00:31,346 : [INFO] [google_photos_backup.py] end : download media 2021-09-10 04:00:31,346 : [INFO] [google_photos_backup.py] start : move files 2021-09-10 04:00:31,347 : [INFO] [google_photos_backup.py] done file moving 2021-09-10 04:00:31,347 : [INFO] [google_photos_backup.py] end : move files 2021-09-10 04:00:31,347 : [INFO] [google_photos_backup.py] start : update aquired list json 2021-09-10 04:00:31,347 : [DEBUG] [google_photos_backup.py] aquired_media_list : aquired_list.json 2021-09-10 04:00:31,353 : [INFO] [google_photos_backup.py] end : update aquired list json 2021-09-10 04:00:31,354 : [INFO] [google_photos_backup.py] All Proccess Complete! 無事定期的にバックアップがとられるようになりました! 難点として現在は大量に一度に取得できないので、初期同期は何か別の方法を考えて行う必要があります。(私はテストもかねてfilterの期間を少しずつ広げながら実行していきました。aquired_listに一度登録されたら次回以降は取得しなくなるので、一度全データがリストに登録されてしまえばフィルター外しても大丈夫です。) また、Google Photo APIは削除の処理が提供されていないので、容量を空けるための削除は手動で行う必要があります。 削除処理が実装されて欲しいですね、、、 参考 【Python】Google Photos API でアルバムの画像取得 PythonでGoogle Photoを50GBの無料サーバーにバックアップ Method: mediaItems.search  |  Google Photos APIs  |  Google Developers tokku5552/google-photo-backup: Get a backup of Google Photos Packaging modules — Ansible Documentation RN214 | ReadyNASストレージ | 製品 | ホーム製品 | NETGEAR ReadyNASでのNFS有効化の方法 | インフラエンジニアがもがくブログ DockerでAnsibleの実行環境を作って家のサーバーを管理する | インフラエンジニアがもがくブログ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

様々な Linuxコマンドとその活用方法について

はじめに この記事ではLinuxコマンドの中で覚えておきたいコマンドと、オプションなどを使用して実際にどのように使用されるかなどについて説明していきたいと思います。 ぜひ参考にしてみてください。 シェルを切り替えるコマンド この章ではシェルを切り替えるときのコマンドについて説明していきたいと思います。 sh シェルをshに切り替える ※4.2はバージョンを示す #bashからshへの切り替え $sh (変更後)sh-4.2$ bash シェルをbashに切り替える #shからbashへの切り替え $-4.2$bash (変更後)$ 元のログイシェル戻るには 元のログイシェル戻るには→exitコマンドを使用 $-4.2$bash (変更後)$ $exit $-4.2$bash←元に戻った ファイルやディレクトリの移動、表示を行うコマンド ここではファイルやディレクトリの移動、表示を行うコマンドについて説明していきます。 その前にコマンドについての理解を深めるために知っておくべき、ディレクトリ、パス(PATH)、そしてパスの書き方で2つに分類できる絶対パスと相対パスについて説明していきたいと思う。 ディレクトリとは Linuxでは文書や画像、プログラムなどだけでなく、実行コマンドや入出力装置など全てがファイルで構成されている(人間がいくつもの細胞で構成されているようなイメージ) →ファイルを種類ごとに分類して認識しやすくすることが大切 (書類を整理しておくような感じ) ディレクトリ→ファイルを整理する入れ物のようなもの ディレクトリの構造とルートディレクトリについて 一般的なLinuxのディレクトリ構造 →ルートディレクトリ(/)を元にそこから枝分かれしていくツリー構造になっている →元を辿るとルートディレクトリ(/で示されている)にたどり着く ※このようなツリー構造をとるものの1つとしてDOMなどが挙げられる パス(PATH)とは 相対バスと絶対パスについて pwd print working directory(出力ディレクトリ)の略 カレントディレクトリ(現在いるディレクトリ)の確認を行う $pwd /home/<ユーザー名> cd カレントディレクトリの変更(移動) $cd /usr $pwd /usr ホームディレクトリへの移動について ホームディレクトリとは? → Linuxのユーザーごとにそれぞれ割り当てられているディレクトリ ①引数なしでcdコマンドを実行した場合 $cd ②~(チルダ)を使って移動→チルダ展開の使用 $cd ~ ls ディレクトリ内のファイルを表示 $ls bin etc など lsコマンドの活用 lsコマンドには様々なオプションが存在するが、今回は特に使用頻度の高いオプションを3つ紹介していきます。 ①ls -lt ファイルが持つ権限や所有者など詳細情報(-lオプション)を更新時間(-tオプション)ごとに並べる $ls -lt ②ls -la lsコマンド →ファイル名が.ではじまるものは隠しファイルとみなして表示しない しかし、-aオプションを付与することで隠しファイルも全て表示される なおかつ詳細な表示がされる $ls -la ③ls -lit ①にさらにノード番号(データに割り当てられる番号)を表示するiコマンドを付与したもの $ls -lit ファイル操作のコマンド mkdir ディレクトリの作成を行う mkdir (オプション) <ディレクトリ名> $mkdir testdir $ls -F testdir/ mkdirコマンドの活用 深いディレクトリの作成 mkdirでディレクトリを作成する際、階層が複数あるディレクトリを作りたいという場合もある →しかし、普通の場合だと $mkdir testdir/hogehoge とした場合、ディレクトリ'testdir/hogehoge'を作成できません という表示になってまう そこで使用されるのが $mkdir -p である。 こちらを使用することで深いディレクトリを作成することができる。 &&の使用 mkdirでディレクトリを作ってすぐにcdコマンドで移動することが多い そんな時に $mkdir testdir $cd testdir と打ってもできるが、できれば一回の処理で終わらせたい。 そんな時は2つのコマンド間にに&&を使用することで連続して処理することができる。 $mkdir testdir && cd testdir touch 何も書かれていない空のファイルの作成 既存のファイルを指定→内容の上書き、削除などはされない またls-lで確認するとわかるが、touchコマンドには実行権限がない 1つ→touch <ファイル名1> 複数→touch <ファイル名1><ファイル名2>.... $touch testfile1 $ls testfile1 cat ファイルの内容の表示 con*cat*enate(連結する)が由来 cat (オプション) <ファイル名> $cat testfile1 --testfile1の内容の表示-- catコマンドの活用 cat -n としてnオプションを付与して 行番号を表示することが多い $cat -n testfile1 1hogehoge 2fugafuga 3hogehoge 4fugafuga less 長いファイルの内容をスクロールで表示 $less --画面に収まらまいほどの内容-- 移動、終了などはvimと同じ 使用される例 使用される例としては cat -n(ファイルの表示)→grep(文字列の検索)→cut(入力の一部を切り出して出力) などの作業を終えた後の最終確認として $less のように 単体で使用されることが多い。また、  $-コマンド-|less としてパイプライン(片方のコマンドにもう片方のコマンドを送り込むこと)で使用されることが多い $less --画面に収まらまいほどの内容-- 移動、終了などはvimと同じ mv ディレクトリー間でのファイルやディレクトリの移動 ファイル名やディレクトリ名の変更を行う 現場では mv -vとして ファイル名やディレクトリ名の変更を行うことが多い vim vim(テキストエディタ)を使用した編集を行う $vim ファイル名 ※注意 vimを使った編集の経験がない場合、ターミナル内でvimtutorを起動し、 コマンドについて慣れてから作業するのがオススメ bashの設定を行うコマンド alias エイリアスの設定 エイリアス→わかりやすい別名(自分で判別できるもの)を与えて、コマンドを使いやすくするための機能、自分で定義付けを行う感じ。 alias <名前>='<コマンド>' またエイリアスで設定したが、本来のように (ls='ls-F'と設定したが、lsのみのコマンドを実行したいなど)使用したい場合 \を先頭につける \ls 自分が設定したエイリアス #はコメントを表す #bashの設定ファイルの内容を読み込んで実行 $source ~/.bashrc #aliasの設定 alias ls='ls -F' alias la='ls -a' alias ll='ls -l' #慎重な操作を行いたいコマンドの実行確認 alias rm='rm -i' alias cp='cp -i' alias mv='mv -I' #深いディレクトリを一気に作成 alias mkdir='mkdir-p' unalias 設定したエイリアスの削除 unalias エイリアス名 $unalias mkdir type 実行コマンドかエイリアスかどうかの判別を行う type 'エイリアス名' $type ll ll is aliased to 'ls-l' ユーザーに様々な権限を付与するコマンド sudo 実行したいコマンドをスーパーユーザーの権限で実行 実行時に一時的にルートユーザーになるのでパスワードの入力が必要となる $sudo yum install git--core [sudo]password for ユーザー名:_
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

様々な Linuxコマンドについて

sh シェルをshに切り替える $sh (変更後)sh-4.2$ bash bashに切り替える $-4.2$bash (変更後)$ pwd カレントディレクトリ(現在いるディレクトリ)の確認 $pwd /home/takei cd カレントディレクトリの変更(移動) $cd /usr $pwd /usr ホームディレクトリへ移動 引数なしで指定 $cd ~(チルダ)を使って移動→チルダ展開の使用 $cd ~ ls ディレクトリ内のファイルを表示 $ls bin etc など mkdir ディレクトリの作成 mkdir (オプション) <ディレクトリ名> $mkdir testdir $ls -F testdir/ touch 何も書かれていない空のファイルの作成 既存のファイルを指定→内容の上書き、削除などはされない 1つ→touch <ファイル名1> 複数→touch <ファイル名1><ファイル名2>.... $touch testfile1 $ls testfile1 cat ファイルの内容の表示 con*cat*enate(連結する)が由来 cat (オプション) <ファイル名> $cat testfile1 --testfile1の内容の表示-- less 長いファイルの内容をスクロールで表示 less (オプション) <ファイル名> $less /testfile1 --画面に収まらまいほどの内容-- 移動、終了などはvimと同じ mv ファイルの移動 mv (オプション) <移動元><移動先> $mv testfile1 testfile2 alias エイリアスの設定 エイリアス→わかりやすい別名(自分で判別できるもの)を与えて、コマンドを使いやすくするための機能、自分で定義付けを行う感じ。 alias <名前>='<コマンド>' またエイリアスで設定したが、本来のように (ls='ls-F'と設定したが、lsのみのコマンドを実行したいなど)使用したい場合 \を先頭につける \ls 自分が設定したエイリアス #はコメントを表す #bashの設定ファイルの内容を読み込んで実行 $source ~/.bashrc #set alias alias ls='ls -F' alias la='ls -a' alias ll='ls -l' #慎重な操作を行いたいコマンドの実行確認 alias rm='rm -i' alias cp='cp -i' alias mv='mv -I' #ディレクトリー作成時に親ディレクトリーも作成 alias mkdir='mkdir-p' unalias 設定したエイリアスの削除 unalias エイリアス名 $unalias mkdir type 実行コマンドかエイリアスかどうかの判別を行う type 'エイリアス名' $type ll ll is aliased to 'ls-l' sudo 実行したいコマンドをスーパーユーザーの権限で実行 実行時に一時的にルートユーザーになるのでパスワードの入力が必要 $sudo yum install git--core [sudo]password for ユーザー名:_ vim vimを使用した編集を行う $vim ファイル名
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む