I am facing a peculiar issue in PowerShell 2.0. I am not an expert in PS, but occasionally write/edit few scripts to work with Nagios monitoring tool. Requesting help form Nagios experts. Your help will be appreciated.
The script ExServiceAlert10.ps1 is embedded below:
#First, findout if Exchange Management Shell is loaded:
$snapins = Get-PSSnapin |select name
$snapincount=0;
$found = $false
do
{
$founDName = $snapins[$snapincount].name
if ($founDName -eq “Microsoft.Exchange.Management.PowerShell.E2010″)
#Exchange Shell already loaded
{
$found = $True
break
}
$snapincount++}
while ($snapincount -lt $snapins.Count)
if ($found -ne $True)
{
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
}
# Create variables
$status = 0
$desc = “”
# Get Service Health
Test-ServiceHealth | ForEach-Object {
$main = “`n" + "Role: " + $_.Role + "`n” + “Status: ” + $_.RequiredServicesRunning + “`n”
if ($_.RequiredServicesRunning -eq “True”){
$array = $_.ServicesRunning
$runningsvcs = “Services running:”
foreach ($svc in $array){
$runningsvcs = $runningsvcs + ” ” + $svc
}
$desc += $main +$runningsvcs + “`n”
}else{
$status = 1
$array = $_.ServicesNotRunning
$notrunning = “Services Not running”
foreach ($svc in $array){
$notrunning = $notrunning + ” ” + $svc
}
$desc += $main + $notrunning
}
}
if ($status -eq 1){
echo “Critical – Exchange Services Alert $desc”
exit 2
}else{
echo “OK – Exchange Services Alert $desc”
exit 0
}
The script is working fine and shows no error, if I directly execute it in PowerShell like this:
PS C:\Windows\system32> D:\ExServiceAlert10.ps1
But it shows error when I execute it via cmd or from Nagios NSClient++ like this:
Normal command Prompt execution: (Script placed at D:)
D:>echo .\ExServiceAlert10.ps1 ; exit $LastExitCode | powershell.exe -command -
From nagios NSclient++ execution via check_nrpe: (Script placed at NSclient Script directory)
cmd /c echo scripts\ExServiceAlert10.ps1; exit $LastExitCode | powershell.exe -command –
The error I am getting is this:
Missing expression after unary opearator ‘-’.
At line:1 char:2
+ – <<<<
+ CategoryInfo : ParseError: (-:String) [], ParentContainsErrorRecordException
+FullyQualifiedErrorId : MissingExpressionAfterOperator
I am executing this script in PowerShell 2.0 and tried various debugging methods to solve this for the past week with no success.
Here are some entries from my NSClient++ conf. file NSC.ini for other PS scripts which are working fine without any issue.
exch_mail_flow10=cmd /c echo scripts\ExchMailFlow10.ps1; exit $LastExitCode | powershell.exe -command -
exch_mailboxhealth10=cmd /c echo scripts\ExMailboxhealth10.ps1; exit $LastExitCode | powershell.exe -command –
Even the reported errant script(ExServiceAlert10.ps1) is working fine in my test system with that extra dash in command prompt but not working at all in any of the the Prod. system. All the PS versions are 2.0.
I think either I have to enable/disable some PS environment settings on those errant Prod. systems, or to escape something inside the script (suspecting newline characters- `n backtick n) . I don’t understand why it is reporting Line:1 and char:2, which is nothing but a comment line in the script.
I have seen this particular error reported by few others and their issue was resolved after upgrading their PS to Ver 2.0. Mine is already 2.0 and don’t know what to do next.
NSC.ini file:
;Nagios agent for BR 1.8 dated Aug 30, 2012. The MSI is updated to 0.3.9 version of nsclient++ and is re-packaged for silent installation. Install.vbs is removed.
[modules]
NRPEListener.dll
NSClientListener.dll
NSCAAgent.dll
CheckWMI.dll
FileLogger.dll
CheckSystem.dll
CheckDisk.dll
CheckEventLog.dll
CheckHelpers.dll
CheckExternalScripts.dll
;# NSCLIENT++ MODULES
;# A list with DLLs to load at startup.
; You will need to enable some of these for NSClient++ to work.
; ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
; * *
; * N O T I C E ! ! ! - Y O U H A V E T O E D I T T H I S *
; * *
; ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
;FileLogger.dll
;CheckSystem.dll
;CheckDisk.dll
;NSClientListener.dll
;NRPEListener.dll
;SysTray.dll
;CheckEventLog.dll
;CheckHelpers.dll
;CheckWMI.dll
;CheckNSCP.dll
;
; Script to check external scripts and/or internal aliases.
;CheckExternalScripts.dll
;
; NSCA Agent if you enable this NSClient++ will talk to NSCA hosts repeatedly (so dont enable unless you want to use NSCA)
;NSCAAgent.dll
;
; LUA script module used to write your own "check deamon".
;LUAScript.dll
;
; RemoteConfiguration IS AN EXTREM EARLY IDEA SO DONT USE FOR PRODUCTION ENVIROMNEMTS!
;RemoteConfiguration.dll
; Check other hosts through NRPE extreme beta and probably a bit dangerous! :)
;NRPEClient.dll
; Extreamly early beta of a task-schedule checker
;CheckTaskSched.dll
[crash]
; Archive crash dump files if a crash is detected
;archive=1
; Submit crash reports to a crash report server (this overrrides archive)
;submit=0
; Restart service if a crash is detected
;restart=1
[Settings]
;# OBFUSCATED PASSWORD
; This is the same as the password option but here you can store the password in an obfuscated manner.
; *NOTICE* obfuscation is *NOT* the same as encryption, someone with access to this file can still figure out the
; password. Its just a bit harder to do it at first glance.
;obfuscated_password=Jw0KAUUdXlAAUwASDAAB
;
;# PASSWORD
; This is the password (-s) that is required to access NSClient remotely. If you leave this blank everyone will be able to access the daemon remotly.
;password=secret-password
;
;# ALLOWED HOST ADDRESSES
; This is a comma-delimited list of IP address of hosts that are allowed to talk to the all daemons.
; If leave this blank anyone can access the deamon remotly (NSClient still requires a valid password).
; The syntax is host or ip/mask so 192.168.0.0/24 will allow anyone on that subnet access
;allowed_hosts=127.0.0.1/32
;
;# USE THIS FILE
; Use the INI file as opposed to the registry if this is 0 and the use_reg in the registry is set to 1
; the registry will be used instead.
use_file=1
allowed_hosts=163.228.10.52
;
; # USE SHARED MEMORY CHANNELS
; This is the "new" way for using the system tray based on an IPC framework on top shared memmory channels and events.
; It is brand new and (probably has bugs) so dont enable this unless for testing!
; If set to 1 shared channels will be created and system tray icons created and such and such...
;shared_session=0
[log]
;# LOG DEBUG
; Set to 1 if you want debug message printed in the log file (debug messages are always printed to stdout when run with -test)
;debug=1
;
;# LOG FILE
; The file to print log statements to
;file=nsclient.log
;
;# LOG DATE MASK
; The format to for the date/time part of the log entry written to file.
;date_mask=%Y-%m-%d %H:%M:%S
;
;# LOG ROOT FOLDER
; The root folder to use for logging.
; exe = the folder where the executable is located
; local-app-data = local application data (probably a better choice then the old default)
;root_folder=exe
[NSClient]
;# ALLOWED HOST ADDRESSES
; This is a comma-delimited list of IP address of hosts that are allowed to talk to NSClient deamon.
; If you leave this blank the global version will be used instead.
;allowed_hosts=
;
;# NSCLIENT PORT NUMBER
; This is the port the NSClientListener.dll will listen to.
port=12489
;
;# BIND TO ADDRESS
; Allows you to bind server to a specific local address. This has to be a dotted ip adress not a hostname.
; Leaving this blank will bind to all avalible IP adresses.
;bind_to_address=
;
;# SOCKET TIMEOUT
; Timeout when reading packets on incoming sockets. If the data has not arrived withint this time we will bail out.
socket_timeout=60
[NRPE]
;# NRPE PORT NUMBER
; This is the port the NRPEListener.dll will listen to.
port=5666
;
;# COMMAND TIMEOUT
; This specifies the maximum number of seconds that the NRPE daemon will allow plug-ins to finish executing before killing them off.
command_timeout=60
;
;# COMMAND ARGUMENT PROCESSING
; This option determines whether or not the NRPE daemon will allow clients to specify arguments to commands that are executed.
allow_arguments=1
;
;# COMMAND ALLOW NASTY META CHARS
; This option determines whether or not the NRPE daemon will allow clients to specify nasty (as in |`&><'"\[]{}) characters in arguments.
allow_nasty_meta_chars=1
;
;# USE SSL SOCKET
; This option controls if SSL should be used on the socket.
;use_ssl=1
;
;# BIND TO ADDRESS
; Allows you to bind server to a specific local address. This has to be a dotted ip adress not a hostname.
; Leaving this blank will bind to all avalible IP adresses.
; bind_to_address=
;
;# ALLOWED HOST ADDRESSES
; This is a comma-delimited list of IP address of hosts that are allowed to talk to NRPE deamon.
; If you leave this blank the global version will be used instead.
;allowed_hosts=
;
;# SCRIPT DIRECTORY
; All files in this directory will become check commands.
; *WARNING* This is undoubtedly dangerous so use with care!
;script_dir=scripts\
;
;# SOCKET TIMEOUT
; Timeout when reading packets on incoming sockets. If the data has not arrived withint this time we will bail out.
;socket_timeout=30
[Check System]
;# CPU BUFFER SIZE
; Can be anything ranging from 1s (for 1 second) to 10w for 10 weeks. Notice that a larger buffer will waste memory
; so don't use a larger buffer then you need (ie. the longest check you do +1).
;CPUBufferSize=1h
;
;# CHECK RESOLUTION
; The resolution to check values (currently only CPU).
; The value is entered in 1/10:th of a second and the default is 10 (which means ones every second)
;CheckResolution=10
;
;# CHECK ALL SERVICES
; Configure how to check services when a CheckAll is performed.
; ...=started means services in that class *has* to be running.
; ...=stopped means services in that class has to be stopped.
; ...=ignored means services in this class will be ignored.
;check_all_services[SERVICE_BOOT_START]=ignored
;check_all_services[SERVICE_SYSTEM_START]=ignored
;check_all_services[SERVICE_AUTO_START]=started
;check_all_services[SERVICE_DEMAND_START]=ignored
;check_all_services[SERVICE_DISABLED]=stopped
[External Script]
;# COMMAND TIMEOUT
; This specifies the maximum number of seconds that the NRPE daemon will allow plug-ins to finish executing before killing them off.
;command_timeout=60
;
;# COMMAND ARGUMENT PROCESSING
; This option determines whether or not the NRPE daemon will allow clients to specify arguments to commands that are executed.
allow_arguments=1
;
;# COMMAND ALLOW NASTY META CHARS
; This option determines whether or not the NRPE daemon will allow clients to specify nasty (as in |`&><'"\[]{}) characters in arguments.
allow_nasty_meta_chars=1
;
;# SCRIPT DIRECTORY
; All files in this directory will become check commands.
; *WARNING* This is undoubtedly dangerous so use with care!
;script_dir=c:\my\script\dir
[Script Wrappings]
vbs=cscript.exe //T:30 //NoLogo scripts\lib\wrapper.vbs %SCRIPT% %ARGS%
ps1=cmd /c echo scripts\%SCRIPT% %ARGS%; exit($lastexitcode) | powershell.exe -command -
bat=scripts\%SCRIPT% %ARGS%
[External Scripts]
;check_es_long=scripts\long.bat
;check_es_ok=scripts\ok.bat
;check_es_nok=scripts\nok.bat
;check_vbs_sample=cscript.exe //T:30 //NoLogo scripts\check_vb.vbs
;check_powershell_warn=cmd /c echo scripts\powershell.ps1 | powershell.exe -command -
dfsdiag_cmd=dfsdiag $ARG1$ $ARG2$
dfsrdiag_cmd=dfsrdiag $ARG1$ $ARG2$
check_log=perl scripts\check_log2.pl -l "$ARG1$" -p1 "$ARG2$" -p2 "$ARG3$" -p3 "$ARG4$" -p4 "$ARG5$"
check_log2=perl scripts\check_log2.pl -l "$ARG1$" -t "$ARG2$" -p1 "$ARG3$" -p2 "$ARG4$" -p3 "$ARG5$" -p4 "$ARG6$"
check_log3=perl scripts\check_log2.pl -l "$ARG1$" -t "$ARG2$" -n "$ARG3$" -p1 "$ARG4$" -p2 "$ARG5$" -p3 "$ARG6$" -p4 "$ARG7$"
check_vlog=perl scripts\check_vlog.pl -l "$ARG1$" -t "$ARG2$" -p1 "$ARG3$" -p2 "$ARG4$" -p3 "$ARG5$" -p4 "$ARG6$"
check_vlog2=perl scripts\check_vlog.pl -l "$ARG1$" -t "$ARG2$" -p1 "$ARG3$" -p2 "$ARG4$" -p3 "$ARG5$" -p4 "$ARG6$" -w "$ARG7$" -c "$ARG8$"
check_log_mp1=perl scripts\check_log_mp.pl -l "$ARG1$" -p "$ARG2$" -t "$ARG3$" -w $ARG4$ -c $ARG5$
check_log_mp2=perl scripts\check_log_mp.pl -l "$ARG1$" -p "$ARG2$" -t "$ARG3$" -n "$ARG4$" -w $ARG5$ -c $ARG6$
check_log_mp3=perl scripts\check_log_mp.pl -l "$ARG1$" -p "$ARG2$" -t "$ARG3$" -n "$ARG4$" -s "$ARG5$" -w $ARG6$ -c $ARG7$
check_foldersize=c:\windows\system32\cscript.exe //NoLogo //T:30 "C:\Program Files\NSClient++\scripts\check_folder_size.vbs" "$ARG1$" $ARG2$ $ARG3$
check_foldersize2=c:\windows\system32\cscript.exe //NoLogo //T:30 "C:\Program Files\NSClient++\scripts\check_folder_size.vbs" "$ARG1$" $ARG2$ $ARG3$ $ARG4$ $ARG5$
check_dfsutil=perl scripts\check_win_dfsutil.pl -H $ARG1$ $ARG2$
dfsutil_cmd=dfsutil $ARG1$ $ARG2$
check_dfsdiag=perl scripts\check_win_dfsdiag.pl -H $ARG1$ -A "$ARG2$"
check_dfsrdiag=perl scripts\check_win_dfsrdiag_backlog.pl -H $ARG1$ -A "$ARG2$" -w $ARG3$ -c $ARG4$
check_file_mtime=perl scripts\check_file_mtime.pl -f "$ARG1$" -t "$ARG2$" "-$ARG3$"
;Citrix WMI monitoring plugins
check_licenses_pl=perl scripts\check_licenseserver.pl -w $ARG1$ -c $ARG2$
check_licenses_vbs=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_ctx_lic.vbs" $ARG1$ $ARG2$ $ARG3$ $ARG4$
check_num_servers_in_zone=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_num_servers_in_zone.vbs" $ARG1$ $ARG2$
check_active_session=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_active_session.vbs" $ARG1$ $ARG2$
check_disconnected_session=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_disconnected_session.vbs" $ARG1$ $ARG2$
check_metaframe_application_loadlevel=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_metaframe_application_loadlevel.vbs" $ARG1$ $ARG2$
check_metaframe_server_loadlevel=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_metaframe_server_loadlevel.vbs" $ARG1$ $ARG2$
check_backupexec=cscript.exe scripts\check_backupexec.vbs //Nologo
check_be=scripts\check_be.exe "C:\Program Files\Symantec\Backup Exec\Data" "$ARG1$" -w"$ARG2$" -c"$ARG3$"
[External Alias]
alias_cpu=checkCPU warn=80 crit=90 time=5m time=1m time=30s
alias_cpu_ex=checkCPU warn=$ARG1$ crit=$ARG2$ time=5m time=1m time=30s
alias_mem=checkMem MaxWarn=80% MaxCrit=90% ShowAll=long type=physical type=virtual type=paged type=page
alias_up=checkUpTime MinWarn=1d MinWarn=1h
alias_disk=CheckDriveSize MinWarn=10% MinCrit=5% CheckAll FilterType=FIXED
alias_disk_loose=CheckDriveSize MinWarn=10% MinCrit=5% CheckAll FilterType=FIXED ignore-unreadable
alias_volumes=CheckDriveSize MinWarn=10% MinCrit=5% CheckAll=volumes FilterType=FIXED
alias_volumes_loose=CheckDriveSize MinWarn=10% MinCrit=5% CheckAll=volumes FilterType=FIXED ignore-unreadable
alias_service=checkServiceState CheckAll
alias_service_ex=checkServiceState CheckAll "exclude=Net Driver HPZ12" "exclude=Pml Driver HPZ12" exclude=stisvc
alias_process=checkProcState "$ARG1$=started"
alias_process_stopped=checkProcState "$ARG1$=stopped"
alias_process_count=checkProcState MaxWarnCount=$ARG2$ MaxCritCount=$ARG3$ "$ARG1$=started"
alias_process_hung=checkProcState MaxWarnCount=1 MaxCritCount=1 "$ARG1$=hung"
alias_event_log=CheckEventLog file=application file=system MaxWarn=1 MaxCrit=1 "filter=generated gt -2d AND severity NOT IN ('success', 'informational') AND source != 'SideBySide'" truncate=800 unique descriptions "syntax=%severity%: %source%: %message% (%count%)"
alias_file_size=CheckFiles "filter=size > $ARG2$" "path=$ARG1$" MaxWarn=1 MaxCrit=1 "syntax=%filename% %size%" max-dir-depth=10
alias_file_age=checkFile2 filter=out "file=$ARG1$" filter-written=>1d MaxWarn=1 MaxCrit=1 "syntax=%filename% %write%"
alias_sched_all=CheckTaskSched "filter=exit_code ne 0" "syntax=%title%: %exit_code%" warn=>0
alias_sched_long=CheckTaskSched "filter=status = 'running' AND most_recent_run_time < -$ARG1$" "syntax=%title% (%most_recent_run_time%)" warn=>0
alias_sched_task=CheckTaskSched "filter=title eq '$ARG1$' AND exit_code ne 0" "syntax=%title% (%most_recent_run_time%)" warn=>0
alias_updates=check_updates -warning 0 -critical 0
check_ok=CheckOK Everything is fine!
[Wrapped Scripts]
;check_test_vbs=check_test.vbs /arg1:1 /arg2:1 /variable:1
;check_test_ps1=check_test.ps1 arg1 arg2
;check_test_bat=check_test.bat arg1 arg2
;check_battery=check_battery.vbs
;check_printer=check_printer.vbs
;check_updates=check_updates.vbs
; [includes]
;# The order when used is "reversed" thus the last included file will be "first"
;# Included files can include other files (be carefull only do basic recursive checking)
;
; myotherfile.ini
; real.ini
[NSCA Agent]
;# CHECK INTERVALL (in seconds)
; How often we should run the checks and submit the results.
;interval=5
;
;# ENCRYPTION METHOD
; This option determines the method by which the send_nsca client will encrypt the packets it sends
; to the nsca daemon. The encryption method you choose will be a balance between security and
; performance, as strong encryption methods consume more processor resources.
; You should evaluate your security needs when choosing an encryption method.
;
; Note: The encryption method you specify here must match the decryption method the nsca daemon uses
; (as specified in the nsca.cfg file)!!
; Values:
; 0 = None (Do NOT use this option)
; 1 = Simple XOR (No security, just obfuscation, but very fast)
; 2 = DES
; 3 = 3DES (Triple DES)
; 4 = CAST-128
; 6 = xTEA
; 8 = BLOWFISH
; 9 = TWOFISH
; 11 = RC2
; 14 = RIJNDAEL-128 (AES)
; 20 = SERPENT
;encryption_method=14
;
;# ENCRYPTION PASSWORD
; This is the password/passphrase that should be used to encrypt the sent packets.
;password=
;
;# BIND TO ADDRESS
; Allows you to bind server to a specific local address. This has to be a dotted ip adress not a hostname.
; Leaving this blank will bind to "one" local interface.
; -- not supported as of now --
;bind_to_address=
;
;# LOCAL HOST NAME
; The name of this host (if empty "computername" will be used.
;hostname=
;
;# NAGIOS SERVER ADDRESS
; The address to the nagios server to submit results to.
;nsca_host=192.168.0.1
;
;# NAGIOS SERVER PORT
; The port to the nagios server to submit results to.
;nsca_port=5667
;
;# CHECK COMMAND LIST
; The checks to run everytime we submit results back to nagios
; Any command(alias/key) starting with a host_ is sent as HOST_COMMAND others are sent as SERVICE_COMMANDS
; where the alias/key is used as service name.
;
[NSCA Commands]
;my_cpu_check=checkCPU warn=80 crit=90 time=20m time=10s time=4
;my_mem_check=checkMem MaxWarn=80% MaxCrit=90% ShowAll type=page
;my_svc_check=checkServiceState CheckAll exclude=wampmysqld exclude=MpfService
;host_check=check_ok
;# REMOTE NRPE PROXY COMMANDS
; A list of commands that check other hosts.
; Used by the NRPECLient module
[NRPE Client Handlers]
check_other=-H 192.168.0.1 -p 5666 -c remote_command -a arguments
;# LUA SCRIPT SECTION
; A list of all Lua scripts to load.
;[LUA Scripts]
;scripts\test.lua
[EventLog]
debug=0
buffer_size=512000
[NRPE Handlers]
exch_dag=cmd /c echo scripts\ExDAG.ps1; exit $LastExitCode; | powershell.exe -command –
exch_mail_flow10=cmd /c echo scripts\ExchMailFlow10.ps1; exit $LastExitCode | powershell.exe -command -
exch_mailboxhealth10=cmd /c echo scripts\ExMailboxhealth10.ps1; exit $LastExitCode | powershell.exe -command –
exch_mapi10=cmd /c echo scripts\ExchMapi10.ps1; exit $LastExitCode | powershell.exe -command -
exch_queue_health10=cmd /c echo scripts\ExQueueHealth10.ps1; exit $LastExitCode | powershell.exe -command -
exch_search10=cmd /c echo scripts\ExchSearch10.ps1; exit $LastExitCode | powershell.exe -command -
exch_service_alert10=cmd /c echo scripts\ExServiceAlert10.ps1; exit $LastExitCode | powershell.exe -command –
;#Windows Update Checker
check_updates=c:\windows\system32\cscript.exe //NoLogo //T:40 "C:\Program Files\NSClient++\scripts\check_updates.wsf" $ARG1$
check_foldersize=c:\windows\system32\cscript.exe //NoLogo //T:30 "C:\Program Files\NSClient++\scripts\check_folder_size.vbs" "$ARG1$" $ARG2$ $ARG3$
check_foldersize2=c:\windows\system32\cscript.exe //NoLogo //T:30 "C:\Program Files\NSClient++\scripts\check_folder_size.vbs" "$ARG1$" $ARG2$ $ARG3$ $ARG4$ $ARG5$
check_dfsutil=perl scripts\check_win_dfsutil.pl -H $ARG1$ $ARG2$
dfsutil_cmd=dfsutil $ARG1$ $ARG2$
dfsdiag_cmd=dfsdiag $ARG1$ $ARG2$
dfsrdiag_cmd=dfsrdiag $ARG1$ $ARG2$
check_dfsdiag=perl scripts\check_win_dfsdiag.pl -H $ARG1$ -A "$ARG2$"
check_dfsrdiag=perl scripts\check_win_dfsrdiag_backlog.pl -H $ARG1$ -A "$ARG2$" -w $ARG3$ -c $ARG4$
check_file_mtime=perl scripts\check_file_mtime.pl -f "$ARG1$" -t "$ARG2$" "-$ARG3$"
;Citrix WMI monitoring plugins
check_licenses_pl=perl scripts\check_licenseserver.pl -w $ARG1$ -c $ARG2$
check_licenses_vbs=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_ctx_lic.vbs" $ARG1$ $ARG2$ $ARG3$ $ARG4$
check_num_servers_in_zone=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_num_servers_in_zone.vbs" $ARG1$ $ARG2$
check_active_session=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_active_session.vbs" $ARG1$ $ARG2$
check_disconnected_session=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_disconnected_session.vbs" $ARG1$ $ARG2$
check_metaframe_application_loadlevel=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_metaframe_application_loadlevel.vbs" $ARG1$ $ARG2$
check_metaframe_server_loadlevel=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_metaframe_server_loadlevel.vbs" $ARG1$ $ARG2$
check_nbu_backup=cmd /c echo scripts\check_nbu_backstat.ps1 -nbuClient $ARG1$; exit $LastExitCode | powershell.exe -command -
check_nbu_backup2=cscript.exe //nologo "C:\Program Files\NSClient++\scripts\check_nbu_backstat.vbs" /nbuClient:$ARG1$ /filePath:"$ARG2$"
check_dcdiag=scripts\check_ad.exe --dc
check_dcdiag2=perl scripts\check_ad.pl --dc
check_dcdiag3=cscript.exe //nologo scripts\check_AD.vbs
Please let me know if any further information is required here. Thank you in advance.
At the end I am able to crack the issue and it was very difficult to find. Our administartor copied/pasted the command line for NSC.ini file from a MS-Word document (How To doc.) shared by me to them. In the original MS-Word doc the hypen (at the end of the line after the word command in the beow given command line) has automatically changed to a little bigger hypen during documentation, which also gone to the NSC.ini file and hence the error was coming for this particular command execution. After changing the hypen manually in the NSC.ini, it worked fine without any issues
Related
If I'm in a deep directory, let's say
/run/media/PhoenixFlame101/Coding/Projects/react-app
the fish prompt currently looks like this:
/r/m/Ph/C/P/react-app >
How do I change it to show only the current directory? Like this:
react-app >
I am also using tide, if that makes any difference.
Edit:
Since #glenn-jackman asked here's the outputs of type fish_prompt:
fish_prompt is a function with definition
# Defined in /home/PhoenixFlame101/.config/fish/functions/fish_prompt.fish # line 2
function fish_prompt
_tide_status=$status _tide_pipestatus=$pipestatus if not set -e _tide_repaint
jobs -q && set -lx _tide_jobs
/usr/bin/fish -c "set _tide_pipestatus $_tide_pipestatus
set _tide_parent_dirs $_tide_parent_dirs
PATH=$(string escape "$PATH") CMD_DURATION=$CMD_DURATION fish_bind_mode=$fish_bind_mode set _tide_prompt_4007 (_tide_2_line_prompt)" &
builtin disown
command kill $_tide_last_pid 2>/dev/null
set -g _tide_last_pid $last_pid
end
math $COLUMNS-(string length -V "$_tide_prompt_4007[1]$_tide_prompt_4007[3]")+5 | read -lx dist_btwn_sides
echo -ns \n''(string replace #PWD# (_tide_pwd) "$_tide_prompt_4007[1]")''
string repeat -Nm(math max 0, $dist_btwn_sides-$_tide_pwd_len) ' '
echo -ns "$_tide_prompt_4007[3]"\n"$_tide_prompt_4007[2] "
end
and type prompt_pwd:
prompt_pwd is a function with definition
# Defined in /usr/share/fish/functions/prompt_pwd.fish # line 1
function prompt_pwd --description 'short CWD for the prompt'
set -l options h/help d/dir-length= D/full-length-dirs=
argparse -n prompt_pwd $options -- $argv
or return
if set -q _flag_help
__fish_print_help prompt_pwd
return 0
end
set -q argv[1]
or set argv $PWD
set -ql _flag_d
and set -l fish_prompt_pwd_dir_length $_flag_d
set -q fish_prompt_pwd_dir_length
or set -l fish_prompt_pwd_dir_length 1
set -l fulldirs 0
set -ql _flag_D
and set fish_prompt_pwd_full_dirs $_flag_D
set -q fish_prompt_pwd_full_dirs
or set -l fish_prompt_pwd_full_dirs 1
for path in $argv
# Replace $HOME with "~"
set -l realhome ~
set -l tmp (string replace -r '^'"$realhome"'($|/)' '~$1' $path)
if test "$fish_prompt_pwd_dir_length" -eq 0
echo $tmp
else
# Shorten to at most $fish_prompt_pwd_dir_length characters per directory
# with full-length-dirs components left at full length.
set -l full
if test $fish_prompt_pwd_full_dirs -gt 0
set -l all (string split -m (math $fish_prompt_pwd_full_dirs - 1) -r / $tmp)
set tmp $all[1]
set full $all[2..]
else if test $fish_prompt_pwd_full_dirs -eq 0
# 0 means not even the last component is kept
string replace -ar '(\.?[^/]{'"$fish_prompt_pwd_dir_length"'})[^/]*' '$1' $tmp
continue
end
string join / (string replace -ar '(\.?[^/]{'"$fish_prompt_pwd_dir_length"'})[^/]*/' '$1/' $tmp) $full
end
end
end
I'm not sure what exactly this does, but I hope it helps!
I want to write a simple PowerShell/Bash script which will run in the background on one productive PC that checks every 1-5 seconds if every chosen member is pingable. If not, the result should be saved to a .txt file with timestamp and IP address. The result should be also saved to .txt file if the latency is greater than e.g. 30 milliseconds.
I already have
ping -t xxx.xxx.xxx.xxx |
ForEach-Object {"{0} - {1}" -f (Get-Date), $_} > C:\Users\xy\pingtest.txt
but this saves every output to the .txt file which won't help me very much.
How can I work from this solution to my desired solution?
Save this script, add permission to execute chmod +x myScript
run it in terminal with watch -n 5 ./myScript
#!/usr/bin/bash
list=(192.168.1.{0..12})
my_time=0.7
file=fileName_"$(date)".txt
for ip in "${list[#]}"; do
ping -c 2 "$ip" >ipOutput.txt
if [[ $? -ne 0 ]]; then
cat <ipOutput.txt >>"$file"
echo "error: $ip $(date) [saving to file]"
else
get_time=$(cat <ipOutput.txt | grep avg | awk -F '/' '{print $5}')
if (($(echo "$get_time" '>='"$my_time" | bc -l))); then
cat <ipOutput.txt >>"$file"
echo "$ip OK, MORE time: $get_time milliseconds [saving to file]"
else
echo "$ip : OK, less than $my_time milliseconds [$get_time]"
fi
fi
done
rm ipOutput.txt
Explaining Answer
Create an array of IP's addresses
list=(192.168.1.{0..12})
you can save in a file a list of iddress to ping and then save it in this variablelist. This is a bash sequence expression {0..12} fills the numbers within a range, this case,from 0 to 12. End result is list=(192.168.1.0 192.168.1.1 192.168.1.2...)
This can be a list of string[domains], example: and works fine
list=("amazon.com" "google.com" "target.com")
create variables:
file=fileName_"$(date)".txt
$(date) this commands adds date to a file[file_with_errors]
iterate array list of ip's
for ip in "${list[#]}"; do
this lines iterates an array with name list access all items with [#], this is a special sintax for bash.
ping each IP 2 times and save it to file
ping -c 2 "$ip" >ipOutput.txt
-c argument, pings an ip a specific number of times, in this case 2 times. After ping, save that OUTPUT to a file[ipOutput.txt] instead of console with >, this save the OUTPUT ONCE for each new IP.
check the OUTPUT from PING and if error exist save it to a file
if [[ $? -ne 0 ]]; then
cat <file.txt >>"$file"
echo "error: $ip $(date) [saving to file]"
$? prints the last output from the last command[PING], and because it's not equal to 0, this means error. cat< ipOutput.txt It shows the content from OUTPUT of PING, and then redirects that data to the variable $file[your_log_file] with >>, this means appends[NO overwrite]. echo prints the text format in terminal
if not error Continue to ELSE statement
else
get_time=$(cat <ipOutput.txt | grep avg | awk -F '/' '{print $5}')
get_time saves the average time that took to ping ip address, in milliseconds.
awk awk is a program for checking columns in text.
-F '/' argument tells awk which delimeter to use, in this case /. {print $5} grabs the number of milliseconds.
output that grabs grep and awk
rtt min/avg/max/mdev = 1.637/1.693/1.749/0.056 ms
Check how long it takes to ping ip address
if (($(echo "$get_time" '>='"$my_time" | bc -l))); then
I reckon the weird of (( )) but for comparison do it. $(commands) is for writing commands and pipes in this case echo, >=, |. The operator >= has to have ' '. | bc -l is for comparing floats in bash.
This is just an IF STATEMENT, but bash needs special sintax for comparing two floats.
save to file because took more TIME to ping of desire time
cat <ipOutput.txt >>"$file".txt
echo "$ip OK, but took MORE time: $get_time milliseconds [saving to file]"
else
echo "$ip : OK, less than $my_time milliseconds [$get_time]"
else everything was ok and NOT saved to file but show ok STATUS in terminal
remove file ipOutput.txt
rm ipOutput.txt
This file was used to save the output for each ip with ping command. This file overwrites the data each new ip, so you can retrieve the info more easy with grep and awk.
This is, what does the trick for me
$processName = "PROCESSNAME"
$basePath = "~\Documents\PingTests"
$archivePath = "~\Documents\PingTests\Archive"
# Set temporary timestamp, which will be used to check, if one day has passed,
# so that the moving and removing of the files will be done just once a day
$dateTemp = (get-date -f dd-MM-yyyy)
# Function to get the current timestamp in the desired format
function Get-TimeStamp {
return "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date)
}
# Create the basePath for the logs
If(!(test-path $basePath)){
New-Item -ItemType Directory -Force -Path $basePath
}
# Create an archivePath for the logs
If(!(test-path $archivePath)){
New-Item -ItemType Directory -Force -Path $archivePath
}
while($True){
# Check, if the desired process is running. This is crucial for the correct execution of the script.
# Only in this case, the current pc is the productive one that has connection to the modbus members.
$process = Get-Process | Where-Object {$_.ProcessName -eq $processName}
if($process){
# List of modbus members, that one wants to monitor
$COMPUTERs="IP-LIST"
# For-Loop that checks every member in "COMPUTERs"
ForEach ($COMPUTER in $COMPUTERs){
# In case the member is not pingable, write it to the .txt file
if(!(Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet)){
# Console output for debugging purposes (not relevant, if execution is done via Task scheduler)
write-host "cannot reach $computer"
# Call of function "Get-TimeStamp"
$timestamp = (Get-TimeStamp)
# Write results to file
"TIMESTAMP: $timestamp, cannot reach IP-ADRESS: $computer" |
out-file -filepath "~\Documents\PingTests\ping_$(get-date -f dd-MM-yyyy).log" -append -width 200
}
# If the member is pingable, check the latency
else {
$Testoutput = Test-Connection -ComputerName $computer -Count 1 | Select -ExpandProperty ResponseTime
Write-Host $Testoutput
# If latency is greater than 30 milliseconds, write the event to the .log file (Testoutput
# has been typecasted, that Powershell can check, if the value is greater than 30ms)
if([int]$Testoutput -gt 30){
# Call of function "Get-TimeStamp"
$timestamp = (Get-TimeStamp)
# Console output for debugging purposes (not relevant, if execution is done via Task scheduler)
write-host $timestamp "," $computer "," $Testoutput
# Write results to file
"TIMESTAMP: $timestamp, IP-ADRESS: $computer , LATENCY: $Testoutput" |
out-file -filepath "~\Documents\PingTests\ping $(get-date -f dd-MM-yyyy).log" -append -width 200
}
}
}
# If one day has passed, move files that are older than 7 days to the archive folder and
# remove files in archive folder, that are older than 30 days
if(!($dateTemp -eq (get-date -f dd-MM-yyyy))){
# Set dateTemp variable to current day
$dateTemp = (get-date -f dd-MM-yyyy)
# Move files
$date1 = (get-date).AddDays(-7)
get-childitem ~\Documents\PingTests\ping *.log | where-object {$_.LastWriteTime -lt $date1} |
move-item -destination ~\Documents\PingTests\Archive
# Remove files
$date2 = (get-date).AddDays(-30)
get-childitem ~\Documents\PingTests\Archive\ping *.log | where-object {$_.LastWriteTime -lt $date2} |
Remove-Item -Force
}
# Wait one second until the next execution
Start-Sleep 1
}
}
I have a strange problem - possibly I'm just going blind. I have this short script, which replaces the string #qry# in the here-document with a select statement in a file and then pipes it to mysql:
#!/bin/bash
if [[ "$1" == "-h" ]]
then
echo "sqljob [sqlfile] [procnm] [host] [database] [config file]"
echo " sqlfile: text file containing an SQL statement"
echo " procnm: name that will given to the new, stored procedure"
echo " host: hostname of IP address of the database server"
echo " database: the procedure will be created here"
echo " config file: default configuration file with username and password"
exit
fi
infile=$1
procnm=$2
hn=$3
pn=$4
db=$5
mycfg=$6
{
set -o noglob
sed -e "s/#qry#/$(echo $(cat $infile))/g" <<!
drop procedure if exists $procnm;
delete from jobs where jobname="$procnm";
insert into jobs
set
notes="SQL job $procnm",
jobname="$procnm",
parm_tmpl='int';
delimiter //
create procedure $procnm(vqid int)
begin
call joblogmsg(vqid,0,"$procnm","","Executing #qry#");
drop table if exists ${procnm}_res;
create table ${procnm}_res as
#qry#
end//
delimiter ;
!
} | mysql --defaults-file=$mycfg -h $hn -P $pn $db
However, when the select contains *, it expands to whatever is in the directory even though I use noglob. However, it works from the command line:
$ set -o noglob
$ ls *
What am I doing wrong?
Edit
Block Comments in a Shell Script has been suggested as a duplicate, but as you will notice, I need to expand ${procnm} in the here-doc; I just need to avoid the same happening to select *.
I suspect it is because the construct echo (cat). The echo command gets the * from the cat command and the shell in which it runs expands it. In that shell set noglob is not active.
Try leaving the echo away: /$(cat $infile)/, in the end that is the data you need; then there is no extra glob expansion by a shell.
I have an issue changing an script I did in bash to powershell, the script is the following:
#! /bin/sh
for IPVAR in 172.27.41.202 172.27.41.203
do
TIEMPO=$(date +"%m-%d-%y")
FILENAME=${IPVAR}_${TIEMPO}
date +"%c" >> $FILENAME.txt
snmpget -v 2c -c public $IPVAR -mALL 1.3.6.1.4.1.41413.1.1.0 1.3.6.1.4.1.41413.1.4.0 1.3.6.1.4.1.41413.1.2.0 1.3.6.1.4.1.41413.1.3.0 1.3.6.1.4.1.41413.10.3.4.1.1.1 1.3.6.1.4.1.41413.10.3.4.1.2.1 1.3.6.1.4.1.41413.10.3.4.1.3.1 1.3.6.1.4.1.41413.10.3.4.1.4.1 1.3.6.1.4.1.41413.10.3.4.1.5.1 1.3.6.1.4.1.41413.10.3.4.1.6.1 1.3.6.1.4.1.41413.10.3.4.1.7.1 1.3.6.1.4.1.41413.10.3.4.1.8.1 1.3.6.1.4.1.41413.10.3.4.1.9.1 1.3.6.1.4.1.41413.10.3.4.1.10.1 >> $FILENAME.txt
done
In my Linux enviroment works fine but I installed NET-SNMP in a Windows Server because there is where we need the files to be but I can seem to make it work I did this:
$IPS = (10.96.90.2)
$TIEMPO = get-date -f yyyy-MM-dd
Foreach ($IPVAR in $IPS) {snmpget -v 2c -c public -m ALL $IPVAR 1.3.6.1.4.1.41413.1.1.0 1.3.6.1.4.1.41413.1.4.0 1.3.6.1.4.1.41413.1.2.0 1.3.6.1.4.1.41413.1.3.0 1.3.6.1.4.1.41413.10.3.4.1.1.1 1.3.6.1.4.1.41413.10.3.4.1.2.1 1.3.6.1.4.1.41413.10.3.4.1.3.1 1.3.6.1.4.1.41413.10.3.4.1.4.1 1.3.6.1.4.1.41413.10.3.4.1.5.1 1.3.6.1.4.1.41413.10.3.4.1.6.1 1.3.6.1.4.1.41413.10.3.4.1.7.1 1.3.6.1.4.1.41413.10.3.4.1.8.1 1.3.6.1.4.1.41413.10.3.4.1.9.1 1.3.6.1.4.1.41413.10.3.4.1.10.1 >> "$IPVAR_$TIEMPO".txt}
If I run only the "snmpget" command it works fine but I have troubles with the scripting part here.
Hope you can help me.
Regards,
Try the code below (this hasn't been tested as I don't have snmpget, but the method works with other command line apps):
$IPS = #('172.27.41.202', '172.27.41.203')
$IPS | ForEach-Object {
$snmpgetParams = #(
'-v', '2c' ,'-c' ,'public' ,'-m' ,'ALL', $_, '1.3.6.1.4.1.41413.1.1.0 1.3.6.1.4.1.41413.1.4.0 1.3.6.1.4.1.41413.1.2.0 1.3.6.1.4.1.41413.1.3.0 1.3.6.1.4.1.41413.10.3.4.1.1.1 1.3.6.1.4.1.41413.10.3.4.1.2.1 1.3.6.1.4.1.41413.10.3.4.1.3.1 1.3.6.1.4.1.41413.10.3.4.1.4.1 1.3.6.1.4.1.41413.10.3.4.1.5.1 1.3.6.1.4.1.41413.10.3.4.1.6.1 1.3.6.1.4.1.41413.10.3.4.1.7.1 1.3.6.1.4.1.41413.10.3.4.1.8.1 1.3.6.1.4.1.41413.10.3.4.1.9.1 1.3.6.1.4.1.41413.10.3.4.1.10.1'
)
$TIEMPO = Get-Date -f yyyy-MM-dd
$FILENAME="$_`_$TIEMPO`.txt"
snmpget #snmpgetParams | Set-Content $FILENAME -Force
}
Line 1 declares an array of IP addresses.
Line 2 starts a foreach loop which will iterate through each IP in the $IPS array.
Lines 3,4,5 create an array of parameters to pass to the snmpget command. The $_ parameter is the current IP address within the loop.
Line 7 sets the $TIEMPO variable with the date.
Line 8 sets the $FILENAME variable with the IP address, followed by an underscore, followed by the date. The backticks ` tell PowerShell to not treat the following characters as part of the preceding variable name. An example filename: 172.27.41.202_2016-08-31.txt
Line 10 calls the snmpget command. The #snmpgetParams 'splats' the parameter array. The output is piped into the Set-Content command, which, with the Force option creates or overwrites the file contents for that IP & date.
Line 11 closes the loop.
i tried to setup squid3 with multiple auth_param. Basically, the first choice should be basic_ldap_auth and if this doesnt return OK it should try basic_ncsa_auth with the same values. As far as i know squid doesnt support it however there is the possibility to use "external" ACL
auth_param basic program /usr/lib/squid3/basic_fake_auth
external_acl_type MultAuth %SRC %LOGIN %{Proxy-Authorization} /etc/squid3/multAuth.pl
acl extAuth external MultAuth
my "multAuth.pl"
use URI::Escape;
use MIME::Base64;
$|=1;
while (<>) {
($ip,$user,$auth) = split();
# Retrieve the password from the authentication header
$auth = uri_unescape($auth);
($type,$authData) = split(/ /, $auth);
$authString = decode_base64($authData);
($username,$password) = split(/:/, $authString);
# do the authentication and pass results back to Squid.
$ldap = `/bin/bash auth/ldap.sh`;
if ($ldap == "OK") {
print "OK";
}
$ncsa = `/bin/bash auth/ncsa.sh`;
if ($ncsa == "OK") {
print "OK";
} else {
print "ERR";
}
}
now i am trying to run with ncsa.sh and ldap.sh the "normal" shell command for these auth methods.
./basic_ldap_auth -R -b "dc=domain,dc=de" -D "CN=Administrator,CN=Users,DC=domain,DC=de" -w "password" -f sAMAccountName=%s -h domain.de
user password
and
./basic_ncsa_auth /etc/squid3/users
user password
Therefor i ran:
auth/ncsa.sh
#!/usr/bin/expect
eval spawn [lrange $argv 0 end]
expect ""
send [lindex $argv 1]
send '\r'
expect {
"OK" {
echo OK
exp_continue
}
"ERR" {
echo ERR
exp_continue
}
interact
with
./ncsa.sh "/usr/lib/squid3/basic_ncsa_auth /etc/squid3/users" "user password"
and i generate the following error:
couldn't execute "/usr/lib/squid3/basic_ncsa_auth /etc/squid3/users": no such file or directory
while executing
"spawn {/usr/lib/squid3/basic_ncsa_auth /etc/squid3/users} {user password}"
("eval" body line 1)
invoked from within
"eval spawn [lrange $argv 0 end]"
(file "./ncsa.sh" line 2)
Besides this error, i am not sure how to pass the variables (username & password) forward and i am also not sure how to answer the shell questions like for example the user & pw input for basic_ldap_auth .
Is there a nice way how to solve that? or any other good plan ?
thanks!
FWIW, the following script helped me transition from passwd based to LDAP based authentication.
Contrary to your requirements, my script acts the other way around: It first checks passwd, then LDAP.
#!/usr/bin/env bash
# multiple Squid basic auth checks
# originally posted here: https://github.com/HackerHarry/mSquidAuth
#
# credits
# https://stackoverflow.com/questions/24147067/verify-user-and-password-against-a-file-created-by-htpasswd/40131483
# https://stackoverflow.com/questions/38710483/how-to-stop-ldapsearch1-from-base64-encoding-userpassword-and-other-attributes
#
# requires ldap-utils, openssl and perl
# tested with Squid 4 using a "auth_param basic program /usr/lib/squid/mSquidAuth.sh" line
# authenticate first against squid password file
# if this fails, try LDAP (Active Directory) and also check group membership
# variables
# sLOGFILE=/var/log/squid/mSquidAuth.log
sPWDFILE="/etc/squid/passwd"
sLDAPHOST="ldaps://dc.domain.local:636"
sBASE="DC=domain,DC=local"
sLDS_OPTIONS="-o ldif-wrap=no -o nettimeout=7 -LLL -P3 -x "
sBINDDN="CN=LDAP-read-user,OU=Users,DC=domain,DC=local"
sBINDPW="read-user-password"
sGROUP="Proxy-Users"
# functions
function _grantAccess {
# echo "access granted - $sUSER" >>$sLOGFILE
echo "OK"
}
function _denyAccess {
# echo "access denied - $sUSER" >>$sLOGFILE
echo "ERR"
}
function _setUserAndPass {
local sAuth="$1"
local sOldIFS=$IFS
IFS=' '
set -- $sAuth
IFS=$sOldIFS
# set it globally
sUSER="$1"
sPASS="$2"
}
# loop
while (true); do
read -r sAUTH
sUSER=""
sPASS=""
sSALT=""
sUSERENTRY=""
sHASHEDPW=""
sUSERDN=""
iDNCOUNT=0
if [ -z "$sAUTH" ]; then
# echo "exiting" >>$sLOGFILE
exit 0
fi
_setUserAndPass "$sAUTH"
sUSERENTRY=$(grep -E "^${sUSER}:" "$sPWDFILE")
if [ -n "$sUSERENTRY" ]; then
sSALT=$(echo "$sUSERENTRY" | cut -d$ -f3)
if [ -n "$sSALT" ]; then
sHASHEDPW=$(openssl passwd -apr1 -salt "$sSALT" "$sPASS")
if [ "$sUSERENTRY" = "${sUSER}:${sHASHEDPW}" ]; then
_grantAccess
continue
fi
fi
fi
# LDAP is next
iDNCOUNT=$(ldapsearch $sLDS_OPTIONS -H "$sLDAPHOST" -D "$sBINDDN" -w "$sBINDPW" -b "$sBASE" "(|(sAMAccountName=${sUSER})(userPrincipalName=${sUSER}))" dn 2>/dev/null | grep -cE 'dn::? ')
if [ $iDNCOUNT != 1 ]; then
# user needs a unique account
_denyAccess
continue
fi
# get user's DN
# we need the extra grep in case we get lines back starting with "# refldap" :/
sUSERDN=$(ldapsearch $sLDS_OPTIONS -H "$sLDAPHOST" -D "$sBINDDN" -w "$sBINDPW" -b "$sBASE" "(|(sAMAccountName=${sUSER})(userPrincipalName=${sUSER}))" dn 2>/dev/null | perl -MMIME::Base64 -n -00 -e 's/\n +//g;s/(?<=:: )(\S+)/decode_base64($1)/eg;print' | grep -E 'dn::? ' | sed -r 's/dn::? //')
# try and bind using that DN to check password validity
# also test if that user is member of a particular group
# backslash in DN needs special treatment
if ldapsearch $sLDS_OPTIONS -H "$sLDAPHOST" -D "$sUSERDN" -w "$sPASS" -b "$sBASE" "name=${sGROUP}" member 2>/dev/null | perl -MMIME::Base64 -n -00 -e 's/\n +//g;s/(?<=:: )(\S+)/decode_base64($1)/eg;print' | grep -q "${sUSERDN/\\/\\\\}"; then
_grantAccess
continue
fi
_denyAccess
done