Check number of active meetings in Big Blue Button from command line - bigbluebutton

I want to check how many active meetings there are on the BBB server at any one time from the command line. I have tried
$ bbb-conf --network
but not getting anywhere. I have also checked the number of active connections to port 80 and 443
$ netstat -anp | grep :443 | grep ESTABLISHED | wc -l
but I'm not sure if I can trust that figure.
I know I can use the isMeetingRunning call from the API but I'm just looking for command line.
Any ideas would be appreciated

The following bash script, which can be run from command line on the same machine as the BigBlueButton server, will process the response to the BBB API getMeetings call.
#!/bin/bash
APICallName="getMeetings"
APIQueryString=""
X=$( bbb-conf --secret | fgrep URL: )
APIEndPoint=${X##* }
Y=$( bbb-conf --secret | fgrep Secret: )
Secret=${Y##* }
S=$APICallName$APIQueryString$Secret
Checksum=$( echo -n $S | sha1sum | cut -f 1 -d ' ' )
if [[ "$APIQueryString" == "" ]]
then
URL="${APIEndPoint}api/$APICallName?checksum=$Checksum"
else
URL="${APIEndPoint}api/$APICallName?$APIQueryString&checksum=$Checksum"
fi
wget -q -O - "$URL" | grep -o '<meetingID>' | wc -w
Tested on a live BBB machine.
Note:
The APICallName and APIQueryString can be modified to provide interface to other BBB API calls. See https://docs.bigbluebutton.org/dev/api.html
The command-line sha1sum will output a different result if a newline is appended to its input. This is the reason echo -n is used instead of echo.
In the last line, the script processes the XML output from the API call in a very naïve way, simply counting the number of occurences of the <meetingID> tag. More elaborate processing would probably require parsing the XML.

Related

Problems with SED in Ansible playbook

I'm installing Docker on some hosts and using Ansible playbook to do this. However, we have a startup script for Consul that breaks when docker is installed, as Docker adds a virtual NIC and adds an extra value to the variable.
Original Variables
NODEIP=`hostname -I`
NODE=`hostname -I |sed 's/[.]/-/g'`
I can manually change them to the following and this works.
NODEIP=$(hostname -I | grep -o "[^ ]\\+" | awk /^10\./"{print $1}")
NODE=$(hostname -I | grep -o "[^ ]\+" | awk /^10\./"{print $1}" |sed "s/[.]/-/g")
However, I need to add these to an Ansible playbook. I've modified the variable for NODE and it gets updated in the script, but NODEIP does not. See sample playbook code below.
name: Fix consul startup script for Docker virtual network interface
shell: sed -i 's/NODEIP=`hostname -I`/s_.*_NODEIP=$(hostname -I | grep -o \"[^ ]\\+\" | awk /^10\./\"{print \$1}\")' filename
shell: sed -i '/NODE=`hostname -I |sed/s_.*_NODE=$(echo $NODEIP|sed 's/[.]/-/g')_' filename
I'm going insane trying to get this to work properly. Can anyone help?
Whenever you run an ansible-playbook, it will gather_facts by default. This task will populate your ansible-playbook execution with the variables listed here: Ansible facts
In your case, you are looking for:
NODEIP={{ ansible_default_ipv4.address }}
NODE={{ ansible_hostname }}
Below code should solve your requirement
- name: Command for NodeIP
shell: hostname -I | grep -o "[^ ]\\+" | awk /^10\./"{print $1}"
register: NODEIP
- name: Command for NodeName
shell: hostname -I | grep -o "[^ ]\+" | awk /^10\./"{print $1}" |sed "s/[.]/-/g"
register: NODE
Above code will store command output to NODEIP and NODE variables respectively.
To learn more about usage of ansible return values, refer https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html
Thanks to all for the input. Here's what I ended up coming up with (had to escape some characters with backslashes). Delighted it works
- name: replace NODEIP variable in consul startup script
lineinfile:
path: filename
regexp: '^NODEIP='
line: "NODEIP=$(hostname -I | grep -o \"[^ ]\\+\" | awk /^10\\./\"{print $1}\")"
backrefs: yes
- name: replace NODE variable in consul startup script
lineinfile:
path: filename
regexp: '^NODE='
line: "NODE=$(hostname -I | grep -o \"[^ ]\\+\" | awk /^10\\./\"{print $1}\" |sed \"s/[.]/-/g\")"
backrefs: yes

Set VSTS output variable to be result from bash command

I'm running a task in VSTS which performs some operations on a variable from a previous step and I then need to output the result to be used in future tasks. I have the following in a command line task running on a linux build host but am having no luck when trying to use the result later with $(podName3).
COMMAND="$(echo '$(pods)' | grep -oh -P '[^ ]*' | grep schema)"
##vso[task.setvariable variable=podName3]"$COMMAND"
I have tried several variations on this to no avail and need some direction as this has stumped me for too long now
Seems the syntax is incorrect.
Just try to below format:
COMMAND="$(echo '$pods' | grep -oh -P '[^ ]*' | grep schema)"
echo "##vso[task.setvariable variable=podName3]$COMMAND"
Or add a powershell task and run below commands to set the variable:
$COMMAND="$(echo '$env:pods' | grep -oh -P '[^ ]*' | grep schema)"
Write-Host "##vso[task.setvariable variable=podName3]$COMMAND"
More information please see Define and modify your variables in a script
I created a command line tool & an Azure DevOps task for this: https://marketplace.visualstudio.com/items?itemName=riezebosch.setvar
It just lets you pipe the output of a command into the tool and output it as the magic variable string. It's written in Go and cross compiled so works on all major platforms and all different shells.
Your example:
echo '$pods' | grep -oh -P '[^ ]*' | grep schema | setvar -name podName3
You only need to include the setvar task prior to this script task in order to get the tool on the agent.
Adding a PSA to this post, looks like they changed the way the variables are accessed now - you have to access variables like this: $(variable)
COMMAND=$(echo '$pods' | grep -oh -P '[^ ]*' | grep schema)
echo "##vso[task.setvariable variable=podName3]$(COMMAND)"

Using /proc/<pid>, how can I identify a network port number's application?

I'm trying to identify what application is running on port 56474 without having root access. I know the application was started by me.
Example:
netstat -tunap
tcp 0 0 0.0.0.0:56474 0.0.0.0:* LISTEN -
I've tried using /proc/pid scripts to walk all using grep on ls -l /proc/pid/fd results. Here is my attempt. NOTE: Not sure if I was heading the right direction
for I in `find /proc/*/fd -exec ls -l {} \; 2>/dev/null | awk -F"->|:" '/socket/ {print $4}' | sort -u | sed -e 's/\[//g' -e 's/\]//g'`; do grep $I /proc/*/net/tcp; done
I had no success. Not sure if there is a way. Thanks.
NOTE: Added another answers as lsof was not satisfactory.
This should work:
#! /bin/bash
port=56474
hex_port=$(echo "obase=16; $port" | bc )
inode=$(cat /proc/net/tcp | grep ":$hex_port" | awk '{print $10}')
for i in $(ps axo pid); do
ls -l /proc/$i/fd 2> /dev/null | grep -q ":\[$inode\]" && echo $i
done
Explanation:
Once we have the port number converted to Hexadecimal, we can get the inode number from /proc/net/tcp (10th field), then we loop through /proc/pids/fd and find a symlink pointing to the inode.
If you're sure the application was started by you then you can use lsof:
/usr/sbin/lsof -nP | grep :56474 | awk '{print $2}'
Another technique to resolve pids and ports of all running apps without root:
1.) Get the pids of running apps. Either use the ActivityManager or parse a ps console output.
2.) iterate through /proc/$pid/net/status files and get the matching uid for a pid.
cat /proc/*pid*/net/status | grep Uid:
3.) Call and parse the output of tcp, tcp6,udp, udp6 files to match ports and uids:
cat /proc/net/tcp
...
4.) match the uids of both matchings, get a port-to-pid map without su access.
Cheers,
goethe

output multi if statements to mail

Using sh on linux I am looking to output the results from multiple if statements to a mail message.
#snap server1
running=`ps -U server1 | wc -l`
if [ $running -eq 1 ]; then
/root/zfsnap/zfSnap.sh -v -a 30d tank/server1
fi
#snap server2
running=`ps -U server2 | wc -l`
if [ $running -eq 1 ]; then
/root/zfsnap/zfSnap.sh -v -a 30d tank/server2
fi
sleep 3 && echo "results of script" | mail -s "snapshot status" administrator#domain.local
## current output is
[root#backupserver ~]# ./backup_script_daily.sh
/sbin/zfs snapshot tank/server1#2013-08-26_12.28.22--30d ... DONE
/sbin/zfs snapshot tank/server2#2013-08-26_12.28.22--30d ... DONE
I'm not really sure how to do this for multiple if statements. I've seen many discussions on individual if statements. I actually have about 8 more (user/servers) in this script. My scripting experience for years has been very low level :). Would it be better to use something like Perl
put servers into array
for each server in array
run command > to text file
end and mail(textfile)
I appreciate any suggestions or ideas and I apologize for any issues with the post. This is my first one.
Kind Regards,
~Jon R.
You can enclose all commands whose output you want to capture in a { } block and pipe the whole thing into the mail command, e.g.:
#!/bin/bash
{
for server in server{1..2}; do
if (( $(pgrep -U "${server}" 2>/dev/null | wc -l) > 0 )); then
/root/zfsnap/zfSnap.sh -v -a 30d "tank/${server}"
fi
done
} | mail -s "snapshot status" administrator#domain.local

Pulling hostname from TNS entry

I am working on a script that will need to determine which node a db being used by a local app is running on. I've been trying to use this as a chance to force myself to learn awk/sed and have a test script to test the statements. It's working off a copy of the tnsnames.ora file I have moved to the home folder the script is located in.
Here is a valid tnsnames.ora stanza:
(
DESCRIPTION = (
ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP) (Host=iplab)(Port=1521))
)
(CONNECT_DATA=(SID=spurs1))
)
After doing some research and getting the awk expression to pull the tns entry to $host I came up with the below script but it doesn't seem to work.
#!/bin/ksh
db=spurs
host=$(awk -v db=$db "/${db}/ {for(i=1; i<=5; i++) {getline; print}}" tnsnames.ora)
echo $host
host= $host | sed 's/Host\s=\s\([a-z]+[0-9]?\)/\1/'
echo $host
When I run it the awk statement I get the following:
(DESCRIPTION = (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP) (Host=hostname)(Port=1521))) (CONNECT_DATA=(SID=spurs1)) )
./tns.ksh: line 6: (DESCRIPTION: not found
(DESCRIPTION = (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP) (Host=hostname)(Port=1521))) (CONNECT_DATA=(SID=spurs1)) )
From what I have seen reading tutorials and forums I think sed is setup correctly and should be setting $host to one or more lowercase letters followed by 0 or 1 numbers after Host = . Since (DESCRIPTION is the start of $host before and after the sed statement I'm not sure how it isn't finding it, an
This worked for me:
tnsping $db | grep HOST | cut -d\ -f 14 | sed 's/).*//g'
On my system I can use this to get the host as long as the host name doesn't have an equals sign (or the actual literal word HOST in the name of the host):
echo $TNS_STRING | sed 's/.HOST//g' | sed 's/).//g' | sed 's/=//g' | sed 's/\s*//g'
Your value for $host is likely a multiline value, so you need to quote it anyplace you use it, i.e.
host=$(awk -v db=$db "/${db}/ {for(i=1; i<=5; i++) {getline; print}}" tnsnames.ora)
echo "$host"
You also need to capture the output (using command-substitution) via $(...)
host=$(echo "$host" | sed 's/Host\s=\s\([a-z]+[0-9]?\)/\1/')
echo "$host"
(and echo it), so it can be processed by sed
Revise
host=$(echo $host | sed 's/.*Host=//; s/).*$//)
echo "$host"
I've switched back to just $host, without the dbl-quotes, as you don't want the linebreaks in the data. Now it is all one big string, and the regex, strips every upto host=, and then strips everything after the first remaining ) char.
If you still get error messages, I don't have access to a tnsnames.ora record, so please edit your query to include a valid record.
I hope this helps.
you may be better relying on the output of tnsping instead of parsing the file: tnsping appears to emit the description on one line:
host=$(
tnsping $db | while read line; do
if [[ "$line" == *HOST* ]]; then
s=${line#*HOST=}; s=${s%%)*}; echo "$s"; break
fi
done
)
This might work for you:
db=spurs
host=$(sed '/^(/,/^)/!d;/^(/{h;d};H;/^)/!d;g;/'"$db"'/!d;s/.*Host=\([^)]*\).*/\1/' tnsnames.ora)
Tested Code:
OIFS=$IFS;
IFS="(";
tns=`tnsping TNS_ALIAS`
tns_arr=($tns);
tns_info=(`(for ((i=0; i<${#tns_arr[#]}; ++i)); do echo "${tns_arr[$i]/)/}"; done)| grep 'HOST\|PORT'|sed 's/)//g'|sed 's/ //g'`)
for ((i=0; i<${#tns_info[#]}; ++i)); do eval "export ${tns_info[$i]}"; done
echo "host:" $HOST
echo "port:" $PORT
IFS=$OIFS;