3

Я знаю свое устройство CD-ROM (/dev/sr0), но как я могу определить по сценарию, пустой ли диск или есть ли в нем диск?

7 ответов7

8

Вы можете получить информацию о любом блочном устройстве с помощью команды blkid .

[root@arch32-vm ~]# blkid /dev/sr0
/dev/sr0: UUID="2013-05-31-23-04-19-00" LABEL="ARCH_201306" TYPE="iso9660" PTTYPE="dos"
[root@arch32-vm ~]# echo $?
0

Если я удаляю диск, я не получаю никаких выходных данных и значение выхода равно 2. (0 означает успех. Ненулевое значение обычно будет означать что-то ненормальное или произошла ошибка)

[root@arch32-vm ~]# blkid /dev/sr0
[root@arch32-vm ~]# echo $?
2
2

setcd -i (в пакете setcd , по крайней мере, в Debian) может сообщить вам состояние диска. В отличие от некоторых других подходов (по крайней мере, смонтировать, вероятно, blkid), он не будет пытаться закрыть лоток, даже на дисках, способных на это. (Что действительно раздражает, если он пытается закрыть вас, когда вы вставляете диск).

С открытым подносом:

$ setcd -i /dev/sr0
/dev/sr0:
  CD tray is open

Сразу после закрытия лотка:

$ setcd -i /dev/sr0
/dev/sr0:
  Drive is not ready

После того, как он готов:

$ setcd -i /dev/sr0
/dev/sr0:
  Disc found in drive: data disc type 1
    Volume name: «name»
    Publisher:                                                                                                                                                                                                                                                                 MKISOFS ISO 9660/HFS FILESYSTEM BUILDER & CDRECORD CD-R/DVD CREATOR (C) 1993 E.YOUNGDALE (C) 1997 J.PEARSON/J.SCHILLING                                                                                                                        2005030913034700�2005030913034700�0000000000000000
    Data preparer:                                                                                                                                 MKISOFS ISO 9660/HFS FILESYSTEM BUILDER & CDRECORD CD-R/DVD CREATOR (C) 1993 E.YOUNGDALE (C) 1997 J.PEARSON/J.SCHILLING                                                                                                                        2005030913034700�2005030913034700�0000000000000000

Закрыто, но нет диска:

$ setcd -i /dev/sr0
/dev/sr0:
  No disc is inserted

Вы можете довольно легко написать это:

while true; do
    cdinfo=$(setcd -i "$dev")
    case "$cdinfo" in
        *'Disc found'*)
            break;
            ;;
        *'not ready'*)
            echo '(waiting for drive to be ready)' >&2;
            sleep 3;
            ;;
        *'is open'*)
            echo '(drive is open)' >&2;
            sleep 5;
            ;;
        *)
            printf 'Confused by setcd -i, bailing out:\n%s\n' "$cdinfo" &2
            exit 1
    esac
done
2

Вы можете попробовать с помощью команды lsblk:

lsblk -fp

Если в строке FSTYPE для строки /dev /sr0 ничего нет -> носитель не загружен в привод cdrom. Если в FSTYPE что-то есть, возможно, iso9660 -> носитель загружен в дисковод cdrom.

Другой, я думаю, самый простой способ:

cat /dev/sr0 | head -1

Если вывод:

cat: /dev/sr0: No medium found

-> нет загруженного носителя.

Если вывод что-то, кроме этого:

cat: /dev/sr0: No medium found

-> медиа загружен.

Обратите внимание: я не пробовал это ни с аудио, ни с пустыми компакт-дисками, но я считаю, что результат будет таким же.

1

Вы можете сделать следующее с Python3 и стандартной библиотекой:

import fcntl
import os

CDROM_DRIVE = '/dev/sr0'

def detect_tray(CDROM_DRIVE):
    """detect_tray reads status of the CDROM_DRIVE.
    Statuses:
    1 = no disk in tray
    2 = tray open
    3 = reading tray
    4 = disk in tray
    """
    fd = os.open(CDROM_DRIVE, os.O_RDONLY | os.O_NONBLOCK)
    rv = fcntl.ioctl(fd, 0x5326)
    os.close(fd)
    print(rv)
1

Проблема с этим подходом сценариев оболочки заключается в том, что ни одна из команд оболочки, mount, lsblk, blkid, не может подождать / заблокировать / приостановить и определить, сообщает ли cdrom "не найден носитель", потому что лоток только что закрыт и инициализируется Сам по себе, чтобы прочитать компакт-диск, или потому, что нет компакт-диска в устройстве, и "не найден носитель" будет сообщено навсегда. Таким образом, вы можете выбрать разумное количество попыток обойти устройство cdrom с определенным интервалом ожидания, прежде чем сдаться, как в приведенном ниже сценарии оболочки, или вы можете написать фрагмент кода c несколькими вызовами ioctl и получить некоторую информацию от CDROM, непосредственно через ядро.

#!/bin/sh

# cd.close
#
# Close the CD-ROM tray, and mount the CD-ROM device:
#
# mount status codes: see man mount(8)
# ------------------------------------
# 0   success
# 1   incorrect invocation or permissions
# 2   system error (out of memory, cannot fork, no more loop devices)
# 4   internal mount bug
# 8   user interrupt
# 16  problems writing or locking /etc/mtab
# 32  mount failure
# 64  some mount succeeded (in the case of mount -a)

CDROM=/dev/sr0
TRIES="1 2 3"
INTERVAL=5
MOUNT=0

TOKENS=( $TRIES )
STOP=${TOKENS[-1]}

for i in $TRIES; do
echo close: ATTEMPT $i of $STOP
output=`mount $CDROM -t iso9660 /cdrom 2>&1`
status=$?
echo mount: OUTPUT $output
echo mount: STATUS $status
if [ $status -eq 0 ]; then
  MOUNT=1
  break
else
  if [[ "$output" =~ "already mounted" ]]; then
    MOUNT=1
    break
  fi
fi
if [ $i -eq $STOP ]; then
  break
fi
echo sleep: $INTERVAL SECONDS...
sleep $INTERVAL
done

if [ $MOUNT -eq 1 ]; then
  echo final: MOUNTED $CDROM
  printf "final: LABEL "
  volname $CDROM
else
  echo final: NO MEDIUM
fi
1

Попробуйте смонтировать устройство.

mount -t iso9660 /dev/sr0 /mnt/cdrom

Затем проверьте возвращаемое значение $?

Если возвращаемое значение равно 0, "хорошо", значит, диск присутствовал. Иначе, он вернет не хорошее "1" или что-либо, кроме "0"

Поэтому, чтобы проверить молча, я бы написал это так.

cdrom_mount=0
mount -t iso9660 /dev/sr0 /mnt/cdrom >/dev/null 2>&1
if [[ $? -gt 0 ]]
    then
    cdrom_mount=true
else
    cdrom_mount=false
fi

Это очень упрощенный пример, но вы можете сделать что-то подобное ...

0

Вот сценарий оболочки, который я использую для своих собственных целей. Это частично основано на ответе Аллана .

Причиной этого является то, что я использовал ее в расширенной команде оболочки, используя && и мне нужно было дождаться, пока устройство будет готово к монтированию.

#!/bin/bash
# mountdvd:
#   A shell script to wait until the optical drive can be mounted.
#
#   Important Notes:
#    - By default, this will wait about 10 seconds for the drive to finish reading a newly
#      inserted disk.
#    - Works best already be given a mount point in /etc/fstab
#    - Works best if fs type is set to auto
#    - Assumes /etc/fstab allows user to mount device
#
#   Example /etc/fstab listing:
#    /dev/cdrom /media/dvd auto nofail,auto,user,exec,utf8,noatime,ro,uid=plex,gid=pi 0 0

# Command name
COMMAND=`basename $0`

# Device to mount
DVD_DEVICE=/dev/cdrom
MOUNT_POINT=/media/dvd

# Number of attempts before giving up (Total time = ATTEMPTS * WAIT_TIME, default: 10 seconds)
ATTEMPTS=20

# Wait time in seconds
WAIT_TIME=0.5

# Check if already mounted first
MOUTPUT=`mountpoint -q $MOUNT_POINT`
MSTATUS=$?

if [ $MSTATUS -eq 0 ]; then
    echo "$COMMAND: $DVD_DEVICE was already mounted."
    exit 0
fi

#for ATTEMPT in {1..$ATTEMPTS}
while [ $ATTEMPTS -gt 0 ];
do
    # Attempt to mount device
    OUTPUT=`mount $DVD_DEVICE 2>&1`
    STATUS=$?

    if [ $STATUS -eq 0 ]; then
        # Device mounted
        exit 0
    else
        # Double check here, just in case earlier check failed.
        if [[ "$OUTPUT" =~ "already mounted" ]]; then
            # Device was already mounted
            echo "$COMMAND: $DVD_DEVICE was already mounted."
            exit 0
        fi
    fi

    if [ $ATTEMPTS -ne 1 ]; then
        # Wait a moment before trying again.
        sleep $WAIT_TIME
    fi

    let ATTEMPTS=ATTEMPTS-1
done

echo "$COMMAND: ERROR: Unable to mount $DVD_DEVICE."
exit 1

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .