Note: You are viewing an old version of this page. View the current version.

Differences between version 3 and previous revision of KnowledgeBase/FreeBSD/VirtualBoxSerialPorts.

Other diffs: Previous Major Revision, Previous Author

Newer page: version 3 Last edited on Tuesday, 1 February 2011 13:38:08 by CyberLeo Revert
Older page: version 2 Last edited on Monday, 31 January 2011 4:41:44 by CyberLeo Revert
@@ -9,5 +9,96 @@
  
 In screen, attach to serial port using screen command entry mode 
 <code brush="bash"> 
 screen ~/.VirtualBox/serial/<vmname>-S0.pty 
+</code>  
+  
+Here's a script that will watch a directory and attach any serial ports it finds to a screen instance:  
+Requires [sysutils/fileschanged|http://www.freshports.org/sysutils/fileschanged/]  
+<code brush="bash">  
+#!/bin/sh  
+  
+# Screen instance identifier  
+screen="serial"  
+  
+# Socket directory  
+sock_dir=/home/cyberleo/.VirtualBox/serial-sock  
+  
+# PTY directory  
+pty_dir=/home/cyberleo/.VirtualBox/serial  
+  
+# Serial logs directory  
+log_dir=/home/cyberleo/.VirtualBox/serial-logs  
+  
+# Make sure they exist  
+mkdir -p "${sock_dir}" "${pty_dir}" "${log_dir}"  
+  
+# Clear out dead screens  
+screen -wipe  
+  
+# If not inside screen, try to attach; if attach fails, try to launch  
+if [ -z "${STY}" ]  
+then  
+ if ! screen -S "${screen}" -x  
+ then  
+ screen -S "${screen}" -d -m -t "Serial" "${0}" "${@}"  
+ sleep 0.25  
+ screen -s "${screen}" -x  
+ fi  
+ exit $?  
+fi  
+  
+# Check if this socket already has a socat running for it  
+is_serial_bound() {  
+ name="${1}"  
+ ps opid,command -U "${USER}" | grep '[s]ocat' | grep -q " ${sock_dir}/${name} "  
+ return $?  
+}  
+  
+# Bind a socket to a pty using socat, and attach a screen to it  
+bind_serial() {  
+ name="${1}"  
+ sock="${2:-${sock_dir}/${name}}"  
+ pty="${3:-${pty_dir}/${name}.pty}"  
+  
+ set -x  
+ # Spawn socat to attach socket to pty  
+ socat "${sock}" pty,link="${pty}" &  
+ sleep 0.25  
+  
+ # Start new screen  
+ screen -S "${screen}" -X screen -t "${name}" "${pty}"  
+ # Set up logging  
+ screen -S "${screen}" -X logfile "${log_dir}/${name}.log"  
+ screen -S "${screen}" -X log on  
+ screen -S "${screen}" -X logfile flush 1  
+ screen -S "${screen}" -X logtstamp on  
+ set +x  
+}  
+  
+# Main loop  
+( ls -1 "${sock_dir}/"* | sort ; fileschanged -s created -f "${sock_dir}" ) | while read sock  
+do  
+ printf "New: %s " "${sock}"  
+  
+ # Ignore anything that is not a socket  
+ if [ ! -S "${sock}" ]  
+ then  
+ echo "Not a socket."  
+ continue  
+ fi  
+  
+ # Ignore already bound serials  
+ if is_serial_bound  
+ then  
+ echo "Already bound."  
+ continue  
+ fi  
+ echo "Binding..."  
+  
+ # Bind  
+ bind_serial "${sock##*/}"  
+  
+ # Rapidfiring commands to screen doesn't work so well  
+ sleep 1  
+done  
 </code> 

version 3

VirtualBox creates serial ports as unix domain sockets, which cannot be used with terminal emulators. Use socat to bind them to ptys, and Gnu Screen can deal with them just fine.

VBoxManage modifyvm <vmname> --uartmode1 server ~/.VirtualBox/serial/<vmname>-S0 # or 1 for uart 2
VBoxManage startvm <vmname>
socat ~/.VirtualBox/serial/<vmname>-S0 pty,link=~/.VirtualBox/serial/<vmname>-S0.pty

In screen, attach to serial port using screen command entry mode

screen ~/.VirtualBox/serial/<vmname>-S0.pty

Here's a script that will watch a directory and attach any serial ports it finds to a screen instance: Requires sysutils/fileschanged

#!/bin/sh

# Screen instance identifier
screen="serial"

# Socket directory
sock_dir=/home/cyberleo/.VirtualBox/serial-sock

# PTY directory
pty_dir=/home/cyberleo/.VirtualBox/serial

# Serial logs directory
log_dir=/home/cyberleo/.VirtualBox/serial-logs

# Make sure they exist
mkdir -p "${sock_dir}" "${pty_dir}" "${log_dir}"

# Clear out dead screens
screen -wipe

# If not inside screen, try to attach; if attach fails, try to launch
if [ -z "${STY}" ]
then
  if ! screen -S "${screen}" -x
  then
    screen -S "${screen}" -d -m -t "Serial" "${0}" "${@}"
    sleep 0.25
    screen -s "${screen}" -x
  fi
  exit $?
fi

# Check if this socket already has a socat running for it
is_serial_bound() {
  name="${1}"
  ps opid,command -U "${USER}" | grep '[s]ocat' | grep -q " ${sock_dir}/${name} "
  return $?
}

# Bind a socket to a pty using socat, and attach a screen to it
bind_serial() {
  name="${1}"
  sock="${2:-${sock_dir}/${name}}"
  pty="${3:-${pty_dir}/${name}.pty}"

  set -x
  # Spawn socat to attach socket to pty
  socat "${sock}" pty,link="${pty}" &
  sleep 0.25

  # Start new screen
  screen -S "${screen}" -X screen -t "${name}" "${pty}"
  # Set up logging
  screen -S "${screen}" -X logfile "${log_dir}/${name}.log"
  screen -S "${screen}" -X log on
  screen -S "${screen}" -X logfile flush 1
  screen -S "${screen}" -X logtstamp on
  set +x
}

# Main loop
( ls -1 "${sock_dir}/"* | sort ; fileschanged -s created -f "${sock_dir}" ) | while read sock
do
  printf "New: %s " "${sock}"

  # Ignore anything that is not a socket
  if [ ! -S "${sock}" ]
  then
    echo "Not a socket."
    continue
  fi

  # Ignore already bound serials
  if is_serial_bound
  then
    echo "Already bound."
    continue
  fi
  echo "Binding..."

  # Bind
  bind_serial "${sock##*/}"

  # Rapidfiring commands to screen doesn't work so well
  sleep 1
done