Powershell: why is it so complicated to run a script? - windows-10

I want to implement some alias-like command that could allow me to navigate through a long directory path by typing less.
In this answer I learned that it's not possible to create aliases for commands like "cd c:\some\dir", but it's possible to create a function, save it into a script and then run it.
So I created a script, saved it in directory C:\ps_scripts, made sure this directory is listed in PATH, then opened PS from C:\ps_scripts and tried to issue command .\script.ps1 and nothing happened - no error, no output, no navigation to the desired directory path. script.ps1 contains the following code:
function fp { set-location "C:\Users\user\puppet\modules\fp\files\configs" }
Then I searched for solution here and tried to run the script by appending powershell -noexit "& as advised in the accepted answer, but got error term '$' is not recognized.
And my execution policy is set to RemoteSigned.
What could be the issue?

You should use appropriate PowerShell profiles for such things, like functions, commands and settings.
You can get the profile path for applicable scope - User (current or all) and host scope (current host or all hosts).
E.g. To get the profile path for current user for all hosts (Windows PowerShell console, ISE), you can type this in PowerShell -
Write-Output $PROFILE.CurrentUserAllHosts
which will tell you the path of profile file that will be used for the scope.
Create a file with same path and name as per output of the command and put your function in that file. This will be automatically loaded for any PowerShell session by current user, and you can use that function without running the script prior manually. This behaves similar to .bashrc file in Linux.
Commands to setup your function in the profile
Run these exact commands in your PowerShell and then restart the PowerShell, it will start working then, and you can use fp after this to call that function from that user profile.
New-Item -Path $PROFILE.CurrentUserAllHosts -Force
Add-Content -Path $PROFILE.CurrentUserAllHosts -Value 'function fp { set-location "C:\Users\user\puppet\modules\fp\files\configs" }'
exit

You put a function definition into the script. You must now call/execute this function somewhere. Your function fp does the same thing as cd C:\Users\user\puppet\modules\fp\files\configs when it is called.
If you want your function to be available at the command prompt, you have to prefix its name with global:, as described here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions?view=powershell-7#function-scope

Related

How to pass application path to task in Azure batch

I am using Azure batch. I have an exe which I need to execute on compute nodes.
I am using this path in the azure portal in my task window "cmd /c %AZ_BATCH_APP_PACKAGE_MyAppCreateRG%\CreateRG.exe -args HelloRG eastUs"
But I am getting an error: The system cannot find the path specified.
For your issue, the error you got is the core point of your problem. You can create a task with the command cmd /c "echo %AZ_BATCH_APP_PACKAGE_MyAppCreateRG%" to show the exact path if it exists or not.
Just like if you want to get the environment variable PATH in windows, you should use the command echo %PATH%. And the result will like below:
So, if it could not show the path you want, it means the environment variable doesn't exist and you should set it up first and check then.
I suggest if you want to execute an exe, you should check if the path of it is right and if the exe already exist for you.
It appears that you have mis-quoted your command to execute. Try:
cmd.exe /c "%AZ_BATCH_APP_PACKAGE_MyAppCreateRG%\CreateRG.exe -args HelloRG eastUs"
As an alternative i am able to execute powershell script instead of exe
powershell C:\Scripts\CreateRG.ps1 -resourceGroup "MyRG" -location "eastUs"

Debugging file transfer using pscp executed from PowerShell

I am trying to use PowerShell to send a file from a Windows 10 dev box to a CentOS 7 server across a local area network.
When I run the following command from PowerShell in the Windows 10 dev box, Putty opens, but then closes before asking for password. And then the test file (index.html) is not present in the intended destination folder on the CentOS 7 server.
Start-Process 'C:\Program Files (x86)\PuTTY\pscp.exe' -ArgumentList ("-scp -pw password C:\projects\temp\junk\index.html some_user_name#192.168.1.5:/home/some_user_name/")
How can I diagnose what problem is causing this command to fail? And what specific steps need to be taken in order for the file to be successfully transferred from the devbox to the server?
I have double checked the obvious things, like the file paths, the user name, and the IP.
The above command is derived from this suggestion by #GrahamGold.
In general, there's nothing wrong with your command. It should work (if all arguments are correct).
To diagnose the problem, first test the command on Windows command-line (cmd.exe):
"C:\Program Files (x86)\PuTTY\pscp.exe" -scp -pw password C:\projects\temp\junk\index.html some_user_name#192.168.1.5:/home/some_user_name/
This way, the output is preserved and you will see, what went wrong (if anything).
The next step is to do the same in PowerShell script using call operator & (though the result should be the same):
& "C:\Program Files (x86)\PuTTY\pscp.exe" -scp -pw password C:\projects\temp\junk\index.html some_user_name#192.168.1.5:/home/some_user_name/
If that works, it's time to replace & with the Start-Process cmdlet, if you really want that. But in general, I do not see a point of that, unless you want to run the transfer asynchronously.
Though if you want to make you command portable, you need to add -hostkey switch.
See my answer to Using echo y as an automated response to a pcp hostkey prompt.

Import PATH environment variable into Bash script launched with cron

When creating Bash scripts, I have always had a line right at the start defining the PATH environment variable. I recently discovered that this doesn't make the script very portable as the PATH variable is different for different versions of Linux (in my case, I moved the script from Arch Linux to Ubuntu and received errors as various executables weren't in the same places).
Is it possible to copy the PATH environment variable defined by the login shell into the current Bash script?
EDIT:
I see that my question has caused some confusion resulting in some thinking that I want to change the PATH environment variable of the login shell with a bash script, which is the exact opposite of what I want.
This is what I currently have at the top of one of my Bash scripts:
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
# Test if an internet connection is present
wget -O /dev/null google.com
I want to replace that second line with something that copies the value of PATH from the login shell into the script environment:
#!/bin/bash
PATH=$(command that copies value of PATH from login shell)
# Test if an internet connection is present
wget -O /dev/null google.com
EDIT 2: Sorry for the big omission on my part. I forgot to mention that the scripts in question are being run on a schedule through cron. Cron creates it's own environment for running the scripts which does not use the environment variables of the login shell or modify them. I just tried running the following script in cron:
#!/bin/bash
echo $PATH >> /home/user/output.txt
The result is as follows. As you can see, the PATH variable used by cron is different to the login shell:
user#ubuntu_router:~$ cat output.txt
/usr/bin:/bin
user#ubuntu_router:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
Don't touch the user's PATH at all unless you have a specific reason. Not doing anything will (basically) accomplish what you ask.
You don't have to do anything to get the user's normal PATH since every process inherits the PATH and all other environment variables automatically.
If you need to add something nonstandard to the PATH, the usual approach is to prepend (or append) the new directory to the user's existing PATH, like so:
PATH=/opt/your/random/dir:$PATH
The environment of cron jobs is pretty close to the system's "default" (for some definition of "default") though interactive shells may generally run with a less constrained environment. But again, the fix for that is to add any missing directories to the current value at the beginning of the script. Adding directories which don't exist on this particular system is harmless, as is introducing duplicate directories.
I've managed to find the answer to my question:
PATH=$PATH:$(sed -n '/PATH=/s/^.*=// ; s/\"//gp' '/etc/environment')
This command will grab the value assigned to PATH by Linux from the environment file and append it to the PATH used by Cron.
I used the following resources to help find the answer:
How to grep for contents after pattern?
https://help.ubuntu.com/community/EnvironmentVariables#System-wide_environment_variables

How to handle change in the $PWD value in shell script?

I have a shell script executed by a tool.
When it is executed by a this tool then the value of $PWD is set by that tool.
However when I executed the script manually the value of $PWD the current directory of script.
Now I'm using this $PWD environmental variable to locate different file location in the script.
But when I execute it manually the file path get changed and it give unexpected results.
Any suggestion how can I handle this change in the value of $PWD while executing the script manually or by that tool?
If you need access to the directory where the script itself is located, in bash you can use
script_dir=$(readlink -f ${0%/*})
It takes the relative path to the script ($0), cuts off the script name and transforms it to a full path.

Ignore 'Security Warning' running script from command line

I am trying to execute a script from shared folder that I trust:
PowerShell -file "\\server\scripts\my.ps1"
But I get a security warning, and have to press 'R' to continue
Security Warning Run only scripts that
you trust. While scripts from the
Internet can be useful, this script
can potentially harm your computer. Do
you want to run
\server\scripts\my.ps1? [D] Do not
run [R] Run once [S] Suspend [?]
Help (default is "D"): d
Can I ignore this warning? The desired pseudo code I want is:
PowerShell -IGNORE_SECURITY_WARNING -file "\\server\scripts\my.ps1"
This is touched in "PowerShell Execution Policies in Standard Images" on Lee Holmes' Blog and "PowerShell’s Security Guiding Principles" on the Windows Power Shell Blog
.
Summary
Some machines treat UNC paths as the big bad internet, so PowerShell treats them as remote files. You can either disable this feature on those servers (UncAsIntranet = 0,) or add the remote machines to your trusted hosts.
If you want to do neither, PowerShell v2 supports an -ExecutionPolicy parameter that does exactly what your pseudocode wants. PowerShell -ExecutionPolicy Bypass -File (...).
To avoid warnings, you can:
Set-ExecutionPolicy bypass
If you're running into this error from a downloaded powershell script, you can unblock the script this way:
Right-click on the .ps1 file in question, and select Properties
Click Unblock in the file properties
Click OK
Just assign 1 to SEE_MASK_NOZONECHECKS env variable
$env:SEE_MASK_NOZONECHECKS = 1
Start-Process $msi_file_path /qn -Wait | out-null
Try this, edit the file with:
notepad foo.ps1:Zone.Identifier
And set 'ZoneId=0'
None of this worked in my specific instance. What did was changing to a NetBIOS name from the FQDN.
Instead of:
\\server.domain.net\file.ps1
use:
\\server\file.ps1
Using the name bypasses the "automatically detect intranet network" config in IE.
See Option 1 in the blog here:
http://setspn.blogspot.com/2011/05/running-powershell-scripts-from-unc.html
I made this powershell script to unblock all files on a share on my server
Get-ChildItem "\\ServerName\e$\MyDirectory\" -Recurse -File | % {
Unblock-File -Path $_.FullName
}
You want to set the execution policy on your machine using Set-ExecutionPolicy:
Set-ExecutionPolicy Unrestricted
You may want to investigate the various execution policies to see which one is right for you. Take a look at the "help about_signing" for more information.
Did you download the script from internet?
Then remove NTFS stream from the file using sysinternal's streams.exe on command line.
cmd> streams.exe .\my.ps1
Now try to run the script again.
Assume that you need to launch ps script from shared folder
copy \\\server\script.ps1 c:\tmp.ps1 /y && PowerShell.exe -ExecutionPolicy Bypass -File c:\tmp.ps1 && del /f c:\tmp.ps1
P.S.
Reduce googling)
It is very simple to do, open your PowerShell and write the following command if you have number of ps1 files. here you have to change the path with your path.
PS C:\Users> Get-ChildItem -Path "D:\downlod" -Recurse | Unblock-File
Try set-executionpolicy "Policyname" -force switch and the warnings pop-up should not come.
For those who want to access a file from an already loaded PowerShell session, either use Unblock-File to mark the file as safe (though you already need to have set a relaxed execution policy like Unrestricted for this to work), or change the execution policy just for the current PowerShell session:
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process

Resources