Я знаю свое устройство CD-ROM (/dev/sr0
), но как я могу определить по сценарию, пустой ли диск или есть ли в нем диск?
7 ответов
Вы можете получить информацию о любом блочном устройстве с помощью команды 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
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
Вы можете попробовать с помощью команды 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
-> медиа загружен.
Обратите внимание: я не пробовал это ни с аудио, ни с пустыми компакт-дисками, но я считаю, что результат будет таким же.
Вы можете сделать следующее с 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)
Проблема с этим подходом сценариев оболочки заключается в том, что ни одна из команд оболочки, 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
Попробуйте смонтировать устройство.
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
Это очень упрощенный пример, но вы можете сделать что-то подобное ...
Вот сценарий оболочки, который я использую для своих собственных целей. Это частично основано на ответе Аллана .
Причиной этого является то, что я использовал ее в расширенной команде оболочки, используя &&
и мне нужно было дождаться, пока устройство будет готово к монтированию.
#!/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