How to manipulate the values of Hashtable for just specific key in powershell? - hashtable

I might need a second set of ideas here.
This is what 'd to achieve:
I need to perform a task in a Hashtable (Powershell) to each value of a particular Key
I am scripting a portion of enabling a dfsr replication and I am stuck because
the follow command needs to be executed:
New-DfsReplicationGroup -GroupName "" | New-DfsReplicatedFolder -FolderName "" | Add-DfsrMember -ComputerName Server1,Server2
If I run the command it self on a powershell terminal works without any problem.
On a Hashtable I already have the follow:
Content of Grouping servers list
Name Value
---- -----
Group Name1 {Server1, Server2}
Group Name2 {Server6, Server9}
Which now has to be easier right?
Thinking as Array:
Write-Verbose "Configuring a full-DFSr connection "
for ($i = 0 ; $i -lt $server_list.Count ; $i++)
{
for ($j = $i + 1 ; $j -lt $server_list.Count ; $j++)
{
Write-Verbose ("Adding bidirectional connections between the member computers named {0} and {1}" -f $server_list[$i],$server_list[$j])
$dfs_connection_status = Add-DfsrConnection -GroupName $GroupName -SourceComputerName $server_list[$i] -DestinationComputerName $server_list[$j]
Write-Output $dfs_connection_status
}
}
However I can't figure it out how to manipulate the content once the key is found
Then I took a break from that script portion and decided to break it down a simple a+b
Take a look on the follow:
where $($key.Name) has
the key value:d and the Value content is:1,4,5
lines as follow
$num = #{a= "Test"
b= "Test2"
c= "Test3"
}
$num.d = #() #adds to an array
$num.d+= '1'
$num.d+= '4'
$num.d+= '5'
$result= $num[0]+$num[1] or if decided $result= $num[0]+$num[2]
result should be '5' or '6' if (1+5)
$num.GetEnumerator() | Sort-Object -Property Value | Where-Object {$_.Key}
Name Value
---- -----
d {1, 4, 5}
a Test
b Test2
c Test3
#$sum+= $num.ContainsKey("d")+$num.ContainsKey("d")+1
$num.GetEnumerator() | Sort-Object -Property Value | Where-Object {$_.Key}
if ($num.ContainsKey("d")) { $num['d'] }
if the d key is found then manipulate the value content as needed . Thinking on my original script for dfsr would be once the group name is found enable the bidirectional replication Server1 -> Server2 and Server2 -> Server1
I could not make it to work so I decided to create a new array (probably is not really needed) what I was thinking okay so you found the d key now lets move all the content to a new array so we can manipulate it.
$vm_list+= $num.Values | Where-Object {$num.ContainsKey("d")} | % ToString
Write-Host "nnt VM_list:t" $($vm_list)
Hope you guys can help
Any idea would it be more than appreciated.

So I found the answer , can't believe it was that easy maybe was loosing my mind.
I am sharing a possible solution to the community ;)
"there is always a multiple ways to get to a place so this could
be one;)"
$script:vmlist = #{} #Hashtable
$vm_list = #() #Array
$vmlist.d = #()
$vmlist.d+= 'Server1'
$vmlist.d+= 'Server2'
if ($vmlist.ContainsKey("d")) #Looking for a particular Key
{
$vmlist['d']
$vm_list+= $vmlist['d']
Write-Host "`n`n`t VM_list:`t`t $($vm_list)`n`n$($vm_list[0])`n$($vm_list[1])`n$($vm_list[2])"
Test-Connection $vm_list[0+1]
}
else {Write-Host "Value not found"}
Printing the content of Hashtable
VM_list: Server1 Server2
Printing the content of the new Array , noted that it will contain the values from the Key d
VM_list[0]:Server1
VM_list[1]:Server2
result:
Source Destination IPV4Address IPV6Address Bytes Time(ms)
------ ----------- ----------- ----------- ----- --------
Server source Server2 10.114.x.y 32 0
Server source Server2 10.114.x.y 32 0
Server source Server2 10.114.x.y 32 0
Server source Server2 10.114.x.y 32 0
Hope you guys can use it
Regards
JCayetano

Related

I have a function in script but I can't find who is calling it

I have a function in script but I can't find who is calling it.
I tried using grep but I can't find it. Maybe it is in different path.
How can I get it from tcl ?
For example, in csh there is an option to use with "echo $0"
I use with linux.
You could try using info frame -1:
proc foo {} {
bar
}
proc bar {} {
puts [info frame -1]
}
foo
# => type proc line 1 cmd bar proc ::foo level 1
So you could read that using dict like dict get [foo] proc and you'll get ::foo, meaning the proc which called bar is foo (in the global namespace).
EDIT: Something you may try to get all the commands executed along the way:
proc a {} {b}
proc b {} {c}
proc c {} {
for {set i 1} {$i < [info level]} {incr i} {
puts [info frame -$i]
}
}
a
# => type proc line 1 cmd c proc ::b level 1
# type proc line 1 cmd b proc ::a level 2
You can use grep to walk thru all the files:
grep -l -R name_of_the_finction /
this will print the filename when this function is called or defined.
Of course there is another way, you activate audit daemon, set to be monitored read operations for this particular file (where the function is defined) and wait. Time to time check the audit logs and you will see process, user, file which open the file in question for read.
If you want to use audit you can check in those articles 1, 2 in my personal blog.

How to exclude parent Unix processes from grepped output from ps

I have got a file of pids and am using ps -f to get information about the pids.
Here is an example..
ps -eaf | grep -f myfilename
myuser 14216 14215 0 10:00 ? 00:00:00 /usr/bin/ksh /home/myScript.ksh
myuser 14286 14216 0 10:00 ? 00:00:00 /usr/bin/ksh /home/myScript.ksh
where myfilename contains only 14216.
I've got a tiny problem where the output is giving me parent process id's as well as the child. I want to exclude the line for the parent process id.
Does anyone know how I could modify my command to exclude parent process keeping in mind that I could have many process id's in my input file?
Hard to do with just grep but easy to do with awk.
Invoke the awk script below from the following command:
ps -eaf | awk -f script.awk myfilename -
Here's the script:
# process the first file on the command line (aka myfilename)
# this is the list of pids
ARGIND == 1 {
pids[$0] = 1
}
# second and subsequent files ("-"/stdin in the example)
ARGIND > 1 {
# is column 2 of the ps -eaf output [i.e.] the pid in the list of desired
# pids? -- if so, print the entire line
if ($2 in pids)
printf("%s\n",$0)
}
UPDATE:
When using GNU awk (gawk), the following may be ignored. For other [obsolete] versions, insert the following code at the top:
# work around old, obsolete versions
ARGIND == 0 {
defective_awk_flag = 1
}
defective_awk_flag != 0 {
if (FILENAME != defective_awk_file) {
defective_awk_file = FILENAME
ARGIND += 1
}
}
UPDATE #2:
The above is all fine. Just for fun, here's an alternate way to do the same thing with perl. One of the advantages is that everything can be contained in the script and no pipeline is necessary.
Invoke the script via:
./script.pl myfilename
And, here's script.pl. Note: I don't write idiomatic perl. My style is more akin to what one would expect to see in other languages like C, javascript, etc.:
#!/usr/bin/perl
master(#ARGV);
exit(0);
# master -- master control
sub master
{
my(#argv) = #_;
my($xfsrc);
my($pidfile);
my($buf);
# NOTE: "chomp" is a perl function that strips newlines
# get filename with list of pids (e.g. myfilename)
$pidfile = shift(#argv);
open($xfsrc,"<$pidfile") ||
die("master: unable to open '$pidfile' -- $!\n");
# create an associative array (a 'hash" in perl parlance) of the desired
# pid numbers
while ($pid = <$xfsrc>) {
chomp($pid);
$pid_desired{$pid} = 1;
}
close($xfsrc);
# run the 'ps' command and capture its output into an array
#pslist = (`ps -eaf`);
# process the command output, line-by-line
foreach $buf (#pslist) {
chomp($buf);
# the pid number we want is in the second column
(undef,$pid) = split(" ",$buf);
# print the line if the pid is one of the ones we want
print($buf,"\n")
if ($pid_desired{$pid});
}
}
Use this command:
ps -eaf | grep -f myfilename | grep -v grep | grep -f myfilename

Using powershell loop with net.exe command error

I'm trying to use powershell to write a script that calls net.exe's delete on a collection of computers meeting the specific case of having 3 or fewer files open. I'm fairly new at this, obviously, as I'm getting odd errors.
Using the example at Microsoft's blog I made the function below out of net session.
Function Get-ActiveNetSessions
{
# converts the output of the net session cmd into a PSobject
$output = net session | Select-String -Pattern \\
$output | foreach {
$parts = $_ -split "\s+", 4
New-Object -Type PSObject -Property #{
Computer = $parts[0].ToString();
Username = $parts[1];
Opens = $parts[2];
IdleTime = $parts[3];
}
}
}
which does produce a workable object that I can apply logic to.
I can use
$computerList = Get-ActiveNetSessions | Where-Object {$_.Opens -clt 3} | Select-Object {$_.Computer} to pull all computers with less than three opens into a variable, too.
What fails is the loop below
ForEach($computer in $computerList)
{
net session $computer /delete
}
with the error
net : The syntax of this command is:
At line:5 char:5
net session $computer /delete
CategoryInfo :NotSpecified (The syntax of this command is::String) [], RemoteException
FullyQualifiedErrorId : NativeCommandError
NET SESSION
[\\computername] [/DELETE] [/LIST]
Trying to run it with a call of $computer = $computer.ToString() ahead of the execution so it sees a string causes the script to hang without dropping the sessions, forcing me to close and reopen the ISE.
What should I do to get this loop working? Any help is appreciated.
Net session expects a \\ before the server name, it looks like. Have you given that a try?

Unix C-Shell: ?Need help for the this task

i have given a task to make a C-shell script. I have list of ip address and device name respectively. For example;
cal 1 : 100.21.25.10
cal 2 : 100.21.25.11
cal 3 : 100.21.25.12
cal 4 : 100.21.25.14
and so on...
Based on this ip and device name, i need to rsh the ip address and get the disk free of the device. The result of disk free will be save to a log. the details of the log will be have device name need to be housekeep. My idea is:
declared array :
set device =( cal1 cal2 cal3)
set ip = (100.21.25.10 100.21.25.11 100.21.25.12 100.21.25.14)
set highspace = 90
foreach data($ip)
set space = rsh $ip df -k
if (${space} >= ${highspace}) then
echo "Please Housekeep $device:" >> $device.log
endif
is this gonna work? Or do you guys have better idea? Thanks.
The C shell should never be used anymore. Neither should rsh; we have ssh now.
Your task in Bourne shell:
#! /bin/sh
highspace=90
fs_to_watch=/path/to/filesystem/that/fills/up
exec 0<"$1"
while read cal calno colon addr; do
space=$(ssh "$addr" df -k "$fs_to_watch" |
awk 'NR > 1 { sub(/%$/, "", $5); print $5 }')
if [ "$space" -gt "$highspace" ]; then
echo "Please Housekeep Cal-$calno"
fi
done

Terminating jq processing when condition is met

I am using jq to search for specific results in a large file. I do not care for duplicate entries matching this specific condition, and it takes a while to process the whole file. What I would like to do is print some details about the first match and then terminate the jq command on the file to save time.
I.e.
jq '. | if ... then "print something; exit jq" else ... end'
I looked into http://stedolan.github.io/jq/manual/?#Breakingoutofcontrolstructures but this didn't quite seem to apply
EDIT:
The file I am parsing contains multiple json objects, one after another. They are not in an array.
Here is an approach which uses a recent version of first/1 (currently in master)
def first(g): label $out | g | ., break $out;
first(inputs | if .=="100" then . else empty end)
Example:
$ seq 1000000000 | jq -M -Rn -f filter.jq
Output (followed by immediate termination)
"100"
Here I use seq in lieu of a large JSON dataset.
To do what is requested is possible using features that were added after the release of jq 1.4. The following uses foreach and inputs:
label $top
| foreach inputs as $line
# state: true means found; false means not yet found
(false;
if . then break $top
else if $line | tostring | test("goodbye") then true else false end
end;
if . then $line else empty end
)
Example:
$ cat << EOF | jq -n -f exit.jq
1
"goodbye"
3
4
EOF
Result:
"goodbye"
You can accomplish it using halt and the inputs builtin:
jq -n 'inputs | if ... then "something", halt else ... end'
Will print "something" and terminate gracefully when the condition matches.
For this to work (i.e. terminate when condition is true), jq needs the -n parameter. See this issue

Resources