【Winodows/Powershell】PowerShell初心者の勉強方法と構築備忘録~共有フォルダを大量作成できるまで~
どうも!新人エンジニアの前歯すきっ歯です🦷
Powershellを触ったことがないのに、
ファイルサーバで共有フォルダを大量作成しなくてはいけない時がやってきました笑
さぁ、今回も頑張りますよ~~
勉強にした時に分かりやすかった資料や自分が作ったコマンドのトラシューを記録しておき、
次に生かしていきたいと思います!!!
💪今回のPowershell勉強で実践したいこと💪
以下3点を実現することにしました。
- 作成したい共有フォルダ一覧のテキスト(list.txt)をCドライブ直下に置いておく。
- D/fs配下にフォルダを大量に作成する。
- それらを全て共有設定にする。
権限は全員が読み書き可能な権限 - 上記各共有フォルダの中にテキストを1つずつ配置する。
テキストの名前は”フォルダ名.txt”となるようにする。
そのテキスト内に”Test”と記載されるようにする。
基礎知識収集
初心者あるあるですが、「共有フォルダ作ってね」と言われても
「共有フォルダってなに?」みたいに「そもそもそれ何ですか?」の状態が多いですよね。
(自分もそうでした)
そんなわけで、共有フォルダ周りで勉強しやすかったリンクをメモしておきます。
【共有フォルダ編】
★共有フォルダという概念について
★ローカルユーザーとローカルグループの作成、権限設定
★共有フォルダの作成方法/共有設定
【Powershell編】
★powershellの概念
今のご時世、学びのスタートは動画でストレスフリーに学びましょう!!
(共有フォルダもYoutubeで検索すると色々出てきますが、そんなに大げさな話じゃないのでリンク先くらいの軽さでちょうどいいかも?)
★powershellのコマンド一覧
これだけで全てを理解することは難しいですが、ど忘れした時や「これって何?」なんて時にこのページに来ると便利かもしれません。変数等の基礎的なルールを教えてくれます。
★フォルダ作成コマンド
★共有フォルダの作成コマンド
★foreachコマンドの基礎
繰り返し何度も実行するのに必要なコマンドです。
「インフラの世界でもJavaとかと一緒なんだなぁ~」と思いました…
ここに来てJavaの勉強が役に立つとは!!!
【実践例編】
★ファイルの作成と共有フォルダの作成
★共有フォルダ作成の様子が分かりやすいリンク
★フォルダの一括作成
★ps1ファイルの作成手順&使用方法
実践編
🙌結論/完成したコマンド🙌
後述のトライ&エラーを解消しできたコマンドは以下の通りです。
foreach ($filename in $(Get-Content -Path "C:\list.txt")){
New-Item -Name $filename -Path "D:\fs" -ItemType directory
New-SmbShare -Name $filename -Path "D:\fs\$filename" -FullAccess everyone
New-Item -Name "$filename.txt" -Path "D:\fs\$filename" -ItemType "file" -Value "Test"
}
コマンド1行目に書かれている通り、list.txtをCドライブ配下に置き、
その中にフォルダ名となる項目を置いています。
トライ&エラーで勉強したことまとめ
IT初心者過ぎるつまずきを沢山したので、忘れぬようにトライ&エラーの記録を作成します。
以下に勉強したことをまとめておきます詳細は後述していきます。
🔶トライ&エラー原因(1):指定したパスとユーザーが準備できていない。
お恥ずかしながら、1行目のNew-Itemコマンドのパスで指定しているC:\配下にfsにフォルダを作っていませんでした笑 また、いると思っていたuse1がどうやらいなかったみたいです…。
foreach ($filename in $(Get-Content -Path "C:\list.txt")){
New-Item -Name $filename -Path "C:\fs" -ItemType directory
New-SmbShare -Name $filename -Path "C:\fs" -FullAccess "user1"
New-Item -Name "$filename.txt" -Path "C:\fs\$filename" -ItemType "file" -Value "Test
}
★コマンドで指定したパスがないエラー
New-SmbShare : The system cannot find the file specified.
At C:\smbshare.ps1:3 char:5
+ New-SmbShare -Name $filename -Path "D:\fs -FullAccess Everyone"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (MSFT_SMBShare:ROOT/Microsoft/Windows/SMB/MSFT_SMBShare) [New-SmbShare], CimException
+ FullyQualifiedErrorId : Windows System Error 2,New-SmbShare
★ユーザーがいないエラー
指定したユーザーがいないと以下のエラーが出ます。今回はフォルダ等を作成することが目的なので、一旦アクセス権限の対象は"everyone"で作成を進めていきます。
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2024/10/09 0:57 a
New-SmbShare : No mapping between account names and security IDs was done.
At line:1 char:118
+ ... directory; New-SmbShare -Name $filename -Path "C:fs" -FullAccess "us ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (MSFT_SMBShare:ROOT/Microsoft/Windows/SMB/MSFT_SMBShare) [New-SmbShare], CimException
+ FullyQualifiedErrorId : Windows System Error 1332,New-SmbShare
▼参考リンク
★上記を踏まえたコマンドの修正
foreach ($filename in $(Get-Content -Path "C:list.txt")){
New-Item -Name $filename -Path "C:fs" -ItemType directory
New-SmbShare -Name $filename -Path "C:fs" -FullAccess "everyone"
New-Item -Name "$filename.txt" -Path "C:\fs\$filename" -ItemType "file" -Value "Test
}
🔶トライ&エラー原因(2):Dドラ配下に共有フォルダを作成する。
Cドラ配下は個人のものだから共有フォルダを作成するべき場所ではないと同僚に教えてもらい、
”(1)修正後”のコマンド内パス指定の部分を以下のように変更しました。
前)C:\fs
後)D:\fs
foreach ($filename in $(Get-Content -Path "C:list.txt")){
New-Item -Name $filename -Path "D:\fs" -ItemType directory;
New-SmbShare -Name $filename -Path "D:\fs" -FullAccess "everyone"
New-Item -Name "$filename.txt" -Path "D:\fs\$filename" -ItemType "file" -Value "Test
}
🔶トライ&エラー原因(3):共有フォルダを作成したい上位階層のフォルダが共有フォルダになっていない。
現在D:\fs配下に共有フォルダを作成しようとしていますが、そもそもそれより上位階層のフォルダが共有されていなければ、外から今回作成するフォルダを見ることができません。
fsが共有フォルダとして設定されていなかったので、共有設定をしてきました。
New-SmbShare : The system cannot find the file specified.
At C:\smbshare.ps1:3 char:5
+ New-SmbShare -Name $filename -Path "D:\fs -FullAccess Everyone"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (MSFT_SMBShare:ROOT/Microsoft/Windows/SMB/MSFT_SMBShare) [New-SmbShare], CimException
+ FullyQualifiedErrorId : Windows System Error 2,New-SmbShare
🔶トライ&エラー原因(4):ファイル(….ps1、list.txtともに)は文字コードを”ANSI”にして保存する
Powershellの結果でも、GUIで作成したフォルダを見ても、日本語のフォルダ名が文字化けをしてしまっていました。以下のリンク先の手順に従って、ファイルを保存し直して実行したところ文字化けが直りました。
New-Item : Illegal characters in path.
At C:\smbshare.ps1:4 char:5
+ New-Item -Name "$filename.txt" -Path "D:\fs\$filename" -ItemType ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-Item], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.NewItemCommand
🔶トライ&エラー原因(5):フォルダ名一覧ファイル内のフォルダ名横にスペースがあってはいけない。
今回の場合はlist.txt内の各フォルダ名の横に空白があることを指します(画像の青い部⇩)
ここで厄介なのは、フォルダ名は空白が消されて作成されるが、コマンドはPowerShell内で空白を含んだフォルダ名で参照することです。
★例:list.txtに”営業本部(空白)”という項目があるとき
◆◆◆エラー状況◆◆◆
以下コマンドを実行すると”営業本部”というフォルダが空白なくできる。
New-Item -Name $filename -Path "D:fs" -ItemType directory
しかし、その後に以下コマンドを実行し上記コマンドで作成したフォルダ配下にファイルを作ろうとすると、「”営業本部(空白)”というフォルダはありません。」というエラーが出る。
New-Item -Name "$filename.txt" -Path "D:\fs\$filename" -ItemType "file" -Value "Test
◆◆◆エラー原因◆◆◆
ファイルを作成するNew-Itemコマンドが実行されるときには、'"D:\fs$filename"'を基にフォルダを探すが、その際に”営業本部(空白)”というフォルダを探しているから。
実際の下記エラーを見ると”営業本部”の次に空白があり、”営業本部 ”という空白を含めたフォルダ名や”営業本部 .txt”というファイル名を探していることが分かる。
New-Item : Could not find a part of the path 'D:\fs\営業本部 \営業本部 .txt'.
At C:\smbshare-SlolveErrorFolder.ps1:4 char:5
+ New-Item -Name "$filename.txt" -Path "D:\fs\$filename" -ItemType ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (D:\fs\営業本部 \営業本部 .txt:String) [New-Item], DirectoryNotFoundException
+ FullyQualifiedErrorId : NewItemIOError,Microsoft.PowerShell.Commands.NewItemCommand
🔶トライ&エラー原因(6):既存で共有設定がある場合はエラーが出る。
ここでのミソは共有フォルダ=フォルダ実態+共有設定で成り立っているということです。
したがって、フォルダを削除しただけでは共有設定が削除されておらず、「共有設定は既にあるよ」という以下のエラーが出てしまいます。したがって、実態のフォルダだけではなく、共有設定まで消す必要があります。
New-SmbShare : The name has already been shared.
At C:\smbshare.ps1:3 char:5
+ New-SmbShare -Name $filename -Path "D:\fs\$filename" -FullAccess ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (MSFT_SMBShare:ROOT/Microsoft/Windows/SMB/MSFT_SMBShare) [New-SmbShare], C
imException
+ FullyQualifiedErrorId : Windows System Error 2118,New-SmbShare
★fsmgmt.mscとは
フォルダを右クリックしてプロパティから共有設定はできるのですが、先にフォルダの実態を削除してしまうとそんなことができません。そこで使うのがfsmgmt.mscです!
詳細は以下リンクをご覧ください。
★fsmgmt.mscの使い方
以下と同様の画面が出てきたら共有を停止したいフォルダを右クリックします。
そうすると”共有の停止”という項目が出てきます。
fsmgmt.mscを開き左側の共有をクリック
共有を停止するフォルダを選択し右クリック
”共有の停止”⇒”はい”の順に選択
★共有フォルダ設定だけではなくDFS名前空間の共有設定が入っている場合でもエラーが出る。
今回ファイルサーバをDFS名前空間のターゲットとしても利用していて、先に名前空間での共有を停止しないと、共有フォルダとしての共有を停止できないというケースがありました。
コマンドのオプションでエラーを出さなくさせる方法
共有を停止する方法を上記でお伝えしましたが、コマンドで”-ErrorAction SilentlyContinue”をつけるとエラーが出なくなります。
New-SmbShare -Name $filename -Path "D:\fs" -FullAccess "everyone" -ErrorAction SilentlyContinue
🔶トライ&エラー原因(7):共有フォルダの "-Path ~"には実際に共有したい階層名を入れる
上記めちゃくちゃ当たり前のことを言っているのですが、失敗をして自分が迷っていたので備忘録です。
正しいコマンド
トライ&エラー(2)修正後の共有設定をするコマンドでは以下です。 1階層分足りません。
誤)New-SmbShare -Name $filename -Path "D:\fs" -FullAccess everyone
結論からいくと、正しくは以下の通りです。"$filename"を足しています。
正)New-SmbShare -Name $filename -Path "D:\fs\$filename" -FullAccess everyone
前提
”人事部”という名前のフォルダを例とします。また、この後登場するフォルダ名"a"はlist.txt内に記載があり、人事部と同じ階層に作られた共有フォルダとします。
list.textの中身です。これまで例にあげてきたフォルダの他にアルファベットをひと通り入れてあります。
1階層分足りない時の状況の詳細
- 共有設定をしたフォルダのパスの途中に他のフォルダの名前がある。
今回”人事部.txt”のある階層のパスは”(IPアドレス)\fs\人事部”の予定でした。しかし、”人事部”フォルダのプロパティから共有されているパスを見ると、(IPアドレス)\a\人事部” のように間に同階層のフォルダ名が混じっていました。(他のフォルダも同様にaの階層が混じる)
- ”人事部.txt”のある階層にアクセスする場合、”(IPアドレス)\a\人事部”と入力する必要がある。
先述の通り、フォルダのパスが本当に”(IPアドレス)\a\人事部”なのか確かめたく、同じドメインに参加させている他ファイルサーバのエクスプローラに”(IPアドレス)\a\人事部”と打ち込むと、”人事部.txt”のある階層にアクセスできてしまいました…。 - ”(IPアドレス)\fs\人事部”と打つと、”(IPアドレス)\fs”の階層にアクセスできる。
先程と同じ他のファイルサーバで”(IPアドレス)\fs\人事部”と入力すると、今度は”D:\fs”の階層に辿り着きました。(この時は謎に思っていましたが、人事部のフォルダの共有する階層として-Pathで”D:\fs”を指定しているので当然の動作ですよね…)
上記事象への推察
上記2点目のような動作となる原因としては、以下のように各階層に対して一意の階層名を付けるためかと考えました。
- ”(IPアドレス)\fs\人事部”と打つと、”(IPアドレス)\fs”の階層にアクセスする設定になっている。
- したがって、本来”(IPアドレス)\fs\人事部”という階層名でアクセスさせている階層と”(IPアドレス)\fs”という階層名でアクセスさせている階層が同じ名前でアクセスできるようになってしまう。
⇒他ファイルサーバ等からアクセスするにあたり、階層名が一意でないと”(IPアドレス)\fs\人事部”と入力した時に”(IPアドレス)\fs\人事部”か”(IPアドレス)\fs”どちらにアクセスさせればよいか分からなくなる。 - コマンドの- Pathで”(IPアドレス)\fs\人事部”と入力した時に”(IPアドレス)\fs”にアクセスするよう指定されたからそちらが優先される。
- 本来”(IPアドレス)\fs\人事部”の階層にも一意の名前を付ける必要があるから、同階層のフォルダ名"a"を挟み本来の”(IPアドレス)\fs\人事部”にアクセスするときには”(IPアドレス)\a\人事部”とした
🙌結論/完成したコマンド🙌 (再掲)
上記のトライ&エラーを解消しできたコマンドは以下の通りです。
foreach ($filename in $(Get-Content -Path "C:\list.txt")){
New-Item -Name $filename -Path "D:\fs" -ItemType directory
New-SmbShare -Name $filename -Path "D:\fs\$filename" -FullAccess everyone
New-Item -Name "$filename.txt" -Path "D:\fs\$filename" -ItemType "file" -Value "Test"
}
Discussion