I am new to U-boot and trying to modify some configuration in the U-boot. I am using STM32MP1 based Avenger96 boiard with Yocto Project and U-boot bootloader. Now I want to modify some U-boot variables like bootcount and bootlimit. For example I want to set bootlimit variable to 4 and if limit is reached, u-boot should run the altbootcmd instead of usual bootcmd.
To make this work I need to edit CONFIG_EXTRA_ENV_SETTINGS statement in the u-boot sources.
But I am not sure how to find the location of this file to be modified.
After spending some time to know about boot process to bring up the board I got to know that it uses boot.cmd file. It contains:
if test -n "${distro_bootpart}"; then
setenv partition "${distro_bootpart}"
else
setenv partition "${bootpart}"
fi
if test ! -e ${devtype} ${devnum}:${partition} boot/fitImage; then
echo "This boot medium does not contain a suitable fitImage file for this system."
echo "devtype=${devtype} devnum=${devnum} partition=${partition} loadaddr=${loadaddr}"
echo "Aborting boot process."
exit 1
fi
part uuid ${devtype} ${devnum}:${partition} uuid
# Some STM32MP1-based systems do not encode the baudrate in the console variable
if test "${console}" = "ttySTM0" && test -n "${baudrate}"; then
setenv console "${console},${baudrate}"
fi
if test -n "${console}"; then
setenv bootargs "${bootargs} console=${console}"
fi
setenv bootargs "${bootargs} root=PARTUUID=${uuid} rw rootwait consoleblank=0"
load ${devtype} ${devnum}:${partition} ${loadaddr} boot/fitImage
if test $? != 0 ; then
echo "Failed to load fitImage file for this system from boot medium."
echo "devtype=${devtype} devnum=${devnum} partition=${partition} loadaddr=${loadaddr}"
echo "Aborting boot process."
exit 2
fi
# A custom script exists to load DTOs
if test -n "${loaddtoscustom}" ; then
# Pull DTOs from fitImage and manually apply them to base DT
if test -n "${loaddtos}" ; then
# Matches UBOOT_DTB_LOADADDRESS in OE layer machine config
setexpr loadaddrdtb 0xcff00000
# Matches UBOOT_DTBO_LOADADDRESS in OE layer machine config
setexpr loadaddrdtbo 0xcff80000
setexpr loaddtossep gsub '#conf' ' fdt' "${loaddtos}"
setexpr loaddtb 1
for i in ${loaddtossep} ; do
if test ${loaddtb} = 1 ; then
echo "Using base DT ${i}"
imxtract ${loadaddr} ${i} ${loadaddrdtb} ;
fdt addr ${loadaddrdtb}
fdt resize
setenv loaddtb 0
else
echo "Applying DTO ${i}"
imxtract ${loadaddr} ${i} ${loadaddrdtbo} ;
fdt apply ${loadaddrdtbo}
fi
done
setenv loaddtb
setenv loaddtossep
setenv loadaddrdtbo
setenv loadaddrdtb
fi
run loaddtoscustom
if test -z "${bootm_args}" ; then
setenv bootm_args "${loadaddr} - ${fdtaddr}"
fi
else
setenv bootm_args "${loadaddr}${loaddtos}"
fi
echo "Booting the Linux kernel..." \
&& bootm ${bootm_args}
Now I want to add something like
bootlimit=5\0" \
rootfspart=4\0" \
bootargs=root=/dev/mmcblk0p${rootfspart} rdinit=/bin/kinit rw single\0" \
altbootcmd=" \
echo Rollback to previous RootFs; "
if test ${rootfspart} = 4; " \
then setenv rootfspart 5; " \
else " \
setenv rootfspart 4; " \
fi; setenv bootcount 0; saveenv; " \
bootcmd\0" \
Can anyone please let me know how can I achieve this? Do I need to create a config fragment to the u-boot recipe or do I need to add patch file? Or is there a better way to implement?
Please let me know if further details are required.
Your help will be much appreciated.
Thanks in advance.
Related
I'm building my first yocto release.
All packages build well and I can build my dts. In fact I have a lot of dtb in my images folder.
This is my build configuration.
Build Configuration:
BB_VERSION = "1.36.0"
BUILD_SYS = "x86_64-linux"
NATIVELSBSTRING = "ubuntu-18.04"
TARGET_SYS = "arm-poky-linux-gnueabi"
MACHINE = "pico-imx6ul-itl"
DISTRO = "fsl-imx-fb"
DISTRO_VERSION = "4.9.88-2.0.0"
TUNE_FEATURES = "arm armv7ve vfp neon callconvention-hard cortexa7"
TARGET_FPU = "hard"
meta
meta-poky = "HEAD:0ec241873367e18f5371a3ad9aca1e2801dcd4ee"
meta-oe
meta-multimedia = "HEAD:dacfa2b1920e285531bec55cd2f08743390aaf57"
meta-freescale = "HEAD:49ac225a38f6d84519798e3264f2e4d19b84f70a"
meta-freescale-3rdparty = "HEAD:1d6d5961dbf82624b28bb318b4950a64abc31d12"
meta-freescale-distro = "HEAD:0ec6d7e206705702b5b534611754de0787f92b72"
meta-bsp
meta-sdk = "HEAD:d65692ecb3a4136fc1cc137152634e8633ddb3c6"
meta-browser = "HEAD:d6f9aed41c73b75a97d71bff060b03a66ee087b1"
meta-gnome
meta-networking
meta-python
meta-filesystems = "HEAD:dacfa2b1920e285531bec55cd2f08743390aaf57"
meta-qt5 = "HEAD:32bb7d18a08d1c48873d7ab6332d4cc3815a4dff"
meta-edm-bsp-release = "added-wifi-drivers:10f5373fedd09c19ffb1a393272e3f3ed83b643a"
This is my machine configuration
##TYPE: Machine
##NAME: pico-imx6ul-itl
##SOC: i.MX6UL
##DESCRIPTION: Machine configuration for PICO-IMX6UL/ULL with QCA(Qualcomm)/BRCM(Broadcom) WLAN module
include conf/machine/include/imx-base.inc
include conf/machine/include/tune-cortexa7.inc
include conf/machine/include/imx6ul-common.inc
MACHINEOVERRIDES = "mx6:mx6ul:"
SOC_FAMILY = "mx6ul"
PREFERRED_PROVIDER_u-boot = "u-boot-edm"
PREFERRED_PROVIDER_u-boot_mx6ul = "u-boot-edm"
PREFERRED_PROVIDER_virtual/bootloader = "u-boot-edm"
PREFERRED_PROVIDER_virtual/bootloader_mx6ul = "u-boot-edm"
UBOOT_MAKE_TARGET = ""
UBOOT_SUFFIX = "img"
SPL_BINARY = "SPL"
UBOOT_MACHINE = "pico-imx6ul_spl_defconfig"
#UBOOT_MACHINE = "./pico-imx6ul_defconfig"
# Ensure uEnv.txt will be available at rootfs time
do_rootfs[depends] += "u-boot-uenv:do_deploy"
UENV_FILENAME = "uEnv.txt"
BOOT_SCRIPTS = "${UENV_FILENAME}:uEnv.txt"
PREFERRED_PROVIDER_virtual/kernel ?= "linux-tn-imx"
PREFERRED_PROVIDER_virtual/kernel_mx6ul = "linux-tn-imx"
# Add kernel modules
MACHINE_EXTRA_RRECOMMENDS += "\
kernel-module-qcacld-tn \
"
KERNEL_DEVICETREE = "imx6ul-pico-qca_dwarf.dtb imx6ul-pico-qca_hobbit.dtb \
imx6ul-pico-qca_nymph.dtb imx6ul-pico-qca_pi.dtb \
imx6ul-pico_dwarf.dtb imx6ul-pico_hobbit.dtb \
imx6ul-pico_nymph.dtb imx6ul-pico_pi.dtb \
imx6ull-pico-qca_dwarf.dtb imx6ull-pico-qca_hobbit.dtb \
imx6ull-pico-qca_nymph.dtb imx6ull-pico-qca_pi.dtb \
imx6ull-pico_dwarf.dtb imx6ull-pico_hobbit.dtb \
imx6ull-pico_nymph.dtb imx6ull-pico_pi.dtb"
KERNEL_IMAGETYPE = "zImage"
MACHINE_FEATURES += "bluetooth pci wifi touchscreen"
MACHINE_EXTRA_RRECOMMENDS += " \
broadcom-bluetooth \
openssh-sftp-server \
libsocketcan \
bash hostapd dnsmasq haveged create-ap iptables \
"
MACHINE_FIRMWARE_remove = "firmware-imx-brcm"
SERIAL_CONSOLE = "115200 ttymxc5"
MACHINE_FEATURES += " usbgadget usbhost "
At the moment I use dd to flash the content of this archive:
core-image-base-pico-imx6ul-itl.sdcard.bz2
u-boot is using this device tree:
imx6ul-pico-qca_pi.dts
But I want this one:
imx6ul-pico_pi.dtb
Can you help me to fix the dts? I can't find a tutorial/documentation for this scenario.
UPDATE
printenv from uboot shell on the board
U-Boot SPL 2017.03-tn-imx_v2017.03_4.9.88_2.0.0_ga-test+g2fb0ee6322 (Apr 09 2019 - 20:13:49)
Boot Device: MMC
Trying to boot from MMC1
Boot Device: MMC
reading u-boot.img
reading u-boot.img
U-Boot 2017.03-tn-imx_v2017.03_4.9.88_2.0.0_ga-test+g2fb0ee6322 (Apr 09 2019 - 20:13:49 +0200)
CPU: Freescale i.MX6UL rev1.0 528 MHz (running at 396 MHz)
CPU: Industrial temperature grade (-40C to 105C) at 24C
Reset cause: POR
Board: PICO-IMX6UL
Compatible baseboard: dwarf, hobbit, nymph, pi
I2C: ready
DRAM: 512 MiB
PMIC: PFUZE3000 DEV_ID=0x30 REV_ID=0x11
MMC: FSL_SDHC: 0
*** Warning - bad CRC, using default environment
No panel detected: default to AT070TN94
Display: AT070TN94 (800x480)
Video: 800x480x24
In: serial
Out: serial
Err: serial
switch to partitions #0, OK
mmc0(part 0) is current device
Net: , FEC1
Normal Boot
Hit any key to stop autoboot: 0
=> printenv
baseboard=pi
baudrate=115200
boot_fdt=try
bootcmd=mmc dev ${mmcdev}; if mmc rescan; then if run loadbootenv; then echo Loaded environment from ${bootenv};run importbootenv;fi;if test -n $uenvcmd; then echo Running uenvcmd ...;run uenvcmd;fi;if run loadbootscript; then run bootscript; fi;if run loadfit; then run fitboot; fi; if run loadimage; then run mmcboot; else echo WARN: Cannot load kernel from boot media; fi; else run netboot; fi
bootdelay=1
bootenv=uEnv.txt
bootscript=echo Running bootscript from mmc ...; source
console=ttymxc5
default_baseboard=pi
detectmem=if test ${memdet} = 512MB; then setenv memsize cma=128M; else setenv memsize cma=96M; fi
eth1addr=00:1f:7b:11:07:27
ethact=FEC1
fdt_addr=0x83000000
fdt_high=0xffffffff
fdtfile=undefined
fit_args=setenv bootargs console=${console},${baudrate} root=/dev/ram0 rootwait rw
fitboot=run fit_args; echo ${bootargs}; bootm 87880000#config#${som}-${form}_${baseboard};
form=pico
image=zImage
importbootenv=echo Importing environment from mmc ...; env import -t -r $loadaddr $filesize
initrd_high=0xffffffff
ip_dyn=no
loadaddr=0x80800000
loadbootenv=fatload mmc ${mmcdev} ${loadaddr} ${bootenv}
loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdtfile}
loadfit=fatload mmc ${mmcdev}:${mmcpart} 0x87880000 tnrescue.itb
loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
mmcargs=setenv bootargs console=${console},${baudrate} ${memsize} root=${mmcroot}
mmcautodetect=yes
mmcboot=echo Booting from mmc ...; run detectmem; run mmcargs; echo baseboard is ${baseboard}; run setfdt; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then echo WARN: Cannot load the DT; echo fall back to load the default DT; setenv baseboard ${default_baseboard}; run setfdt; run loadfdt; bootz ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;
mmcdev=0
mmcpart=1
mmcroot=/dev/mmcblk0p2 rootwait rw
netargs=setenv bootargs console=${console},${baudrate} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
netboot=echo Booting from net ...; if test ${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; run loadbootenv; run importbootenv; run setfdt; run netargs; ${get_cmd} ${loadaddr} ${image}; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if ${get_cmd} ${fdt_addr} ${fdtfile}; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;
script=boot.scr
setfdt=if test ${wifi_module} = qca; then setenv fdtfile ${som}-${form}-${wifi_module}_${baseboard}.dtb; else setenv fdtfile ${som}-${form}_${baseboard}.dtb;fi
som=imx6ul
splashpos=m,m
wifi_module=qca
Environment size: 2920/8188 bytes
You need to modify the wifi_module field of your uboot.
At this time, when you boot, the command setfdtsets the device tree to ${som}-${form}-${wifi_module}_${baseboard}.dtb if ${wifi_module} = qca.
To remove this line type:
setenv wifi_module
After that type
run bootcmd
This will allow you to test the modification. After a reboot it will come back to wifi_module = qca so you can save the environment to make it persistent:
setenv wifi_module
saveenv
See Section 4.12.4 of the Yocto Reference Manual.
To reiterate here, "Functionality is automatically enabled for any recipe that inherits the kernel class and sets the KERNEL_DEVICETREE variable".
For example, in my machine config for ZynqMP which is ARM64 based, I set
KERNEL_DEVICETREE = "xilinx/zynqmp-zcu102-ged.dtb"
For your example, I believe specifying the below should suffice in your machine configuration.
KERNEL_DEVICETREE = "imx6ul-pico_pi.dtb"
I can not run /etc/init.d/dbora.
When running through the terminal it reports the following problem:
Shell
[root#localhost init.d]# ./dbora start Starting... Processing Database
instance "ORA11G": log file
/ora01/app/oracle/product/11.2.0/db_1/startup.log Environment variable
ORACLE_UNQNAME not defined. Please set ORACLE_UNQNAME to database
unique name.
My User Linux: oracle
Script
!/bin/bash
# versao: 1.0
export TMP=/tmp
export ORACLE_HOSTNAME=centos7.dbaora.com
export ORACLE_UNQNAME=oracle
export ORACLE_BASE=/ora01/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/11.2.0/db_1
export ORACLE_SID=ORA11G
export ORACLE_OWNER=oracle
PATH=/usr/sbin:$PATH:$ORACLE_HOME/bin
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib;
export CLASSPATH=$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib;
alias cdob='cd $ORACLE_BASE'
alias cdoh='cd $ORACLE_HOME'
alias tns='cd $ORACLE_HOME/network/admin'
alias envo='env | grep ORACLE'
umask 022
start(){
echo "Starting..."
su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/dbstart $ORACLE_HOME"
su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/emctl start dbconsole"
touch /var/lock/subsys/dbora
}
stop(){
echo "Stopping..."
su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/emctl stop dbconsole"
su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/dbshut $ORACLE_HOME"
rm -f /var/lock/subsys/dbora
}
restart(){
stop
start
}
usage(){
echo "usage: $0 {start|stop|restart}"
}
if [ `id -u` -ne 0 ]
then
echo "Este script deve ser executado como root"
exit
fi
case $1 in
'start') start;;
'stop') stop;;
'restart') restart;;
*) usage;;
esac
ORACLE_UNQNAME is an OS environmental variable used by Oracle Enterprise Manager; it supports managing multiple databases from one OEM instance.
It looks like you haven't set a value yourself, probably because you only have the one database so it's already unique, right :) Nevertheless you need to give it a different value from oracle: orcl is traditional and will do the trick. In Linux you can set it from the command line using export like any other environment variable, or just change the value in your script.
I hope this is an easy answer
Problems:
I placed the following bash script called learn-address.sh in the following folder:
vi /etc/openvpn/netem/learn-address.sh
Added the following (2) lines to the .conf file:
script-security 3
learn-address /etc/openvpn/netem/learn-address.sh
And applied the following permission to the learn-address script:
chmod 755 /etc/openvpn/netem/learn-address.sh
However, the script does update the files ($ip.classid and $ip.dev)
in the tmp file and passes the variables correctly
But the bash script does not execute the tc class and filter commands (there is no change to qdisc)
What permissions would I use on the script to execute the tc class and filter commands when the learn-address script is called when a user connects to OpenVPN or is there something else that I missed?
Many thanks
Name of script: learn-address.sh
#!/bin/bash
statedir=/tmp/
function bwlimit-enable() {
ip=$1
user=$2
dev=eth0
# Disable if already enabled.
bwlimit-disable $ip
# Find unique classid.
if [ -f $statedir/$ip.classid ]; then
# Reuse this IP's classid
classid=`cat $statedir/$ip.classid`
else
if [ -f $statedir/last_classid ]; then
classid=`cat $statedir/last_classid`
classid=$((classid+1))
else
classid=1
fi
echo $classid > $statedir/last_classid
fi
# Find this user's bandwidth limit
# downrate: from VPN server to the client
# uprate: from client to the VPN server
if [ "$user" == "myuser" ]; then
downrate=10mbit
uprate=10mbit
elif [ "$user" == "anotheruser"]; then
downrate=2mbit
uprate=2mbit
else
downrate=5mbit
uprate=5mbit
fi
# Limit traffic from VPN server to client
tc class add dev $dev parent 1: classid 1:$classid htb rate $downrate
tc filter add dev $dev protocol all parent 1:0 prio 1 u32 match ip dst $ip/32 flowid 1:$classid
# Limit traffic from client to VPN server
tc filter add dev $dev parent ffff: protocol all prio 1 u32 match ip src $ip/32 police rate $uprate burst 80k drop flowid :$classid
# Store classid and dev for further use.
echo $classid > $statedir/$ip.classid
echo $dev > $statedir/$ip.dev
}
function bwlimit-disable() {
ip=$1
if [ ! -f $statedir/$ip.classid ]; then
return
fi
if [ ! -f $statedir/$ip.dev ]; then
return
fi
classid=`cat $statedir/$ip.classid`
dev=`cat $statedir/$ip.dev`
tc filter del dev $dev protocol all parent 1:0 prio 1 u32 match ip dst $ip/32
tc class del dev $dev classid 1:$classid
tc filter del dev $dev parent ffff: protocol all prio 1 u32 match ip src $ip/32
# Remove .dev but keep .classid so it can be reused.
rm $statedir/$ip.dev
}
# Make sure queueing discipline is enabled.
tc qdisc add dev $dev root handle 1: htb 2>/dev/null || /bin/true
tc qdisc add dev $dev handle ffff: ingress 2>/dev/null || /bin/true
case "$1" in
add|update)
bwlimit-enable $2 $3
;;
delete)
bwlimit-disable $2
;;
*)
echo "$0: unknown operation [$1]" >&2
exit 1
;;
esac
exit 0
The calls to tc here are occurring before dev is defined, which happens later after you've parsed the function arguments and either called bwlimit-enable or bwlimit-disable. It looks like you want to move those two calls:
# Make sure queueing discipline is enabled.
tc qdisc add dev $dev root handle 1: htb 2>/dev/null || /bin/true
tc qdisc add dev $dev handle ffff: ingress 2>/dev/null || /bin/true
... to below the case statement.
I have problems with notifications on zabbix to telegram messenger.
So, I specified different guides for that. But not successful.
For example I use this guides
This solutions works for bash. But I can send this from zabbix.
export to=$1;
export subject=$2;
export body=$3;
tgpath=/usr/src/tg/zabbix
cd ${tgpath}
(sleep 5; echo "msg $to $subject $body"; echo "safe_quit") |
${tgpath}/telegram-cli -k /etc/telegram-cli/mykey.pub -W
Key telegram-cli -e does not work correctly with a login name and with format user#XXXXXX;
I dont want to use some API to send message.
Thank you for any help.
Your script is not equal to the blog post.
The steps are:
0 - Compile
cd /usr/src
git clone --recursive https://github.com/vysheng/tg.git
cd tg
./configure
make
mkdir viacron
cp bin/telegram-cli viacron/
cp tg-server.pub viacron/
cd viacron
1 - Create a file /usr/src/tg/viacron/telegram.config an put this:
default_profile = "viacron";
viacron = {
config_directory = "/usr/src/tg/viacron/";
};
2 - Create a file /usr/src/tg/viacron/telegram.config an put this:
#!/bin/bash
MAIN_DIRECTORY="/usr/src/tg/viacron/"
USER=$1
SUBJECT=$2
TEXT=$3
cd $MAIN_DIRECTORY
if [[ $? -ne 0 ]]; then
echo "Error to enter in the main directory"
exit 1
fi
./telegram-cli -k tg-server.pub -c telegram.config -WR -e "msg $USER $SUBJECT" || exit 1
exit 0
3 - Change permissions:
chmod +x /usr/src/tg/viacron/telegram_standalone.sh
chown -R yourUser: /usr/src/tg/
4 - Test:
/usr/src/tg/viacron/telegram_standalone.sh user#12345 "GNU is not unix"
5 - Put AlertScriptsPath=/usr/src/tg/viacron/ in zabbix_server.conf and restart the server
6 - In zabbix, add new media type with name telegram_standalone.sh
More information in https://gist.github.com/gnumoksha/a95f237d82733ce1f748 and http://tobias.ws/blog/zabbix-com-notificacoes-pelo-telegram/
Now Telegram supported by default
check:
https://www.zabbix.com/integrations/telegram
and there is extra settings check:
https://youtu.be/TpP6NpS9jjg?t=143
I have a bash script called sr_run_batch.sh which does super resolution of images. Now I want to do testing on different servers in parallel at the same time. ie. 1 Virtual machine at one given point of time. then 2 virtual machines at one point of time , 3 and then 4.
I tried writing into it the commands
for host in $(cat hosts.txt); do ssh "$host" "$command" >"output.$host"; done
ssh-keygen && for host in $(cat hosts.txt); do ssh-copy-id $host; done
where the file hosts.txt contains the list of servers: username#ip(format) but when I run this, it gives me substitution error
Hence, I tried pssh (parallel-ssh)
pssh -h hosts-file -l username -P $command
command being ./sr_run_batch.sh
but it didn't run, so I modified this to
pssh -h hosts-file -l ben -P -I<./sr_run_batch.sh
But, for some unknown reason, it just prints the echo statements in the code.
here is the code :
NList=(5)
VList=(1)
FList=("input/flower1.jpg" "input/flower2.jpg" "input/flower3.jpg" "input/flower4.jpg")
IList=("320X240" "640X480" "1280X960" "1920X1200")
SList=(2 3)
for VM in ${VList[#]}; do
for ((index=0; index < ${#FList};)) do
file=$FList[$index]
image_size=$IList[$index]
width=`echo $image_size|cut -d "X" -f1`
height=`echo $image_size|cut -d "X" -f2`
for scale_factor in ${SList[#]}; do
for users in ${NList[#]}; do
echo "V: $VM, " "F: $file, " "S: $scale_factor, " "I: $width $height , " "N: $users"
for i in `seq 1 $users` ; do
./sr_run_once.sh $file $width $height $scale_factor &
done
wait
done # for users
done # for scale_factor
done # for index
done # for VM
exit 0
Have you also tried to use pssh with a simple bash-script so see if the communication is set up ok?
$ pssh -h hosts.txt -A -l ben -P -I<./uptime.sh
Warning: do not enter your password if anyone else has superuser
privileges or access to your account.
Password:
10.0.0.67: 11:06:50 up 28 min, 2 users, load average: 0.00, 0.00, 0.00
[1] 11:06:50 [SUCCESS] 10.0.0.67
10.0.0.218: 11:06:50 up 24 min, 2 users, load average: 0.00, 0.05, 0.20
[2] 11:06:50 [SUCCESS] 10.0.0.218